圈地為王示例

2021-06-22 01:09:23 字數 4658 閱讀 3865

// 圈地為王遊戲樣例程式

// 最後更新 2013-06-25 21:56

#include #include #include #include #include #include #define initial_owner -1 // 無主

#define temporary_flag -2 // 臨時標誌

#define max(a, b) ((b < a) ? (a) : (b))

#define min(a, b) ((a < b) ? (a) : (b))

#define player_count 4

#define field_width 10

#define field_height 10

using namespace std;

struct point

point()

bool operator<(const point& b) const

bool operator==(const point& b) const

bool operator!=(const point& b) const

void operator+=(const point& b) };

int playerleft, myid, turncount, vborders[field_width + 1][field_height], hborders[field_width][field_height + 1], //記錄軌跡用

vborderowner[field_width + 1][field_height], hborderowner[field_width][field_height + 1], // 記錄可否行走用

grids[field_width][field_height], areasquaresum[player_count], areasum[player_count], // 記錄格仔占領情況

dx[5] = , dy[5] = , playerstate[player_count], // 0為抬筆,1為落筆,-1為死亡

stuckstatusleft[player_count], // 玩家被束縛剩餘回合數

scoredecline[player_count]; // 玩家因施放技能損失的分數

char actions[5] = ,

lastdir[player_count]; // 上次走的方向,僅用於落筆後狀態

point prevpos[player_count], currpos[player_count];

vectortrail[player_count];

settraps;

struct enclosingargu

};inline void drawline(int charid, point& prevpos, point& currpos)

inline bool movestep(int &x, int &y, int dir, int charid) // 移動並檢查是否撞到charid邊界

else if (dir == 1)

else if (dir == 2)

else if (dir == 3)

x += dx[dir];

y += dy[dir];

if (x < 0 || x >= field_width || y < 0 || y >= field_height)

return false;

return true;

}inline bool movestep(int &x, int &y, int dir) // 移動

int tryexpand(int charid, int tempboard[field_width][field_height], int gridx, int gridy,

set& actuallyoccupiedarea, bool willbedead[player_count]) // 試圖用漫水法找出charid所圍全部區域

if (gridx > 0 && gridx < field_width && gridy > 0 && gridy < field_height &&

hborders[gridx - 1][gridy] != charid && hborders[gridx][gridy] != charid &&

vborders[gridx][gridy - 1] != charid && vborders[gridx][gridy] != charid)

if (initialowner == initial_owner)

actuallyoccupiedarea.insert(point(gridx, gridy));

return area + 1;

}int tryexpand(int tempboard[field_width][field_height], int gridx, int gridy, set& allarea) // 試圖用漫水法從gridx/y開始找出內容為tempflag的連續格仔面積

return area + 1;

}// 產生圈地的引數,因為根據規則,在正式圈地之前還要從小到大排序

enclosingargu calcenclose(int charid, vector::iterator p, vector::iterator e) // p~e是真正在邊界上的點

// 按照圈地引數進行正式圈地

void doenclose(const enclosingargu& argu)

// 標記所有內部邊

point x1, x2;

for (x1.x = 0; x1.x < field_width; x1.x++)

for (x1.y = 0; x1.y < field_height; x1.y++)

if (x1.y < field_height - 1)

};areasum[argu.charid] += argu.actuallyoccupiedarea.size();

setallarea;

// 找出所有連續的區域

for (i = argu.actuallyoccupiedarea.begin(); i != e; i++)

if (tempgrids[i->x][i->y] == temporary_flag)

;// 清除軌跡

int x, y;

for (x = 0; x <= field_width; x++)

for (y = 0; y <= field_height; y++)

;trail[argu.charid].clear();

}bool checkroute(int charid, int state, point& prevpos, point& currpos) // 檢查路線是否可以行走

else

if (currpos.x == 0 || currpos.x == field_width)

return true;

else }

inline bool checkposvalidity(point& pos)

inline bool isreverse(int dir1, int dir2) // 判斷方向是否相反

inline int getdistance(int ida, int idb) // 獲得兩名角色之間的座標差

int main()

if (y != field_height)

if (x != field_width && y != field_height)

grids[x][y] = initial_owner;

};for (i = 0; i < player_count; i++)

turncount = 0;

while (cin >> cmd)

if (cmd == "[status]")

if (++turncount == 1) // 第一回合

for (i = 0; i < player_count; i++)

prevpos[i] = currpos[i];

else

else if (playerstate[i] == 1)}}

for_each(allenclosure.begin(), allenclosure.end(), doenclose);

allenclosure.clear();

}if (stuckstatusleft[myid] > 0)

if (playerstate[myid] == 0)

else if (rand() % 2)

else

changepenstate = 0;

}else

changepenstate = 0;

if (playerstate[myid] == 1) // 落筆態

if (i != 4)

lastdir[myid] = i;

}else // 抬筆態

while (true)

;cout << "[action] " << actions[i] << ' ' << changepenstate << endl;

for (i = 0; i < player_count; i++)

prevpos[i] = currpos[i];

}}}

GMOJ4016 圈地為王

在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,你不能圈住它。求圈住 i...

JZOJ 4016 圈地為王

description 在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,...

搜尋,計算幾何 JZOJ 4016 圈地為王

在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,你不能圈住它。求圈住 i...