柚子快報邀請碼778899分享:【C語言】五子棋(c語言實現(xiàn))
柚子快報邀請碼778899分享:【C語言】五子棋(c語言實現(xiàn))
這里寫目錄標題
最終效果菜單打印函數(shù)棋盤的初始化和打印人人對戰(zhàn)落子判空函數(shù)悔棋函數(shù)判勝負函數(shù)人人對戰(zhàn)
人機對戰(zhàn)一是將直接調(diào)用rand生成隨機值,這就不可控二是根據(jù)棋子贏面來判斷哪里落子最好
如果選擇退出程序直接exit就行主函數(shù)調(diào)用邏輯源代碼
最終效果
五子棋c語言實現(xiàn)
菜單打印函數(shù)
使用這個函數(shù)來接收用戶選擇的模式,并通過返回值返回。 邏輯是使用一個死循環(huán)來打印,根據(jù)玩家輸入的數(shù)來判斷進入什么模式,輸入錯誤數(shù)字就不出循環(huán),正確就出循環(huán)。
int menu()
{
int choice = -1;
while (1)
{
printf("----------------歡迎使用五子棋------------------------\n");
printf("- 請選擇模式 -\n");
printf("- 1.人-人對戰(zhàn)游戲 -\n");
printf("- 2.人-機對戰(zhàn)游戲 -\n");
printf("- 0.退出游戲 -\n");
printf("------------------------------------------------------\n");
printf("------------------------------------------------------\n");
scanf("%d", &choice);
if (choice > 4 || choice < 0)
printf("錯誤輸入");
else
break;
}
return choice;
}
棋盤的初始化和打印
在這個函數(shù)中將表示棋盤的二維數(shù)組初始化為空狀態(tài),并通過棋盤數(shù)組的只來打印棋盤。打印棋盤時用到的符號:┏ ┳ ┓┣ ╋ ┫┗ ┻ ┛。要注意有些地方添加━和空格來控制打印的棋盤是正確的。 里面每一次打印都調(diào)用draw_chessman這個函數(shù),在這個函數(shù)中將根據(jù)數(shù)組值來判斷如何打印。
//繪制棋子
void draw_chessman(int type, char* tableline) {
if (type == WHITE)
printf(" ●");
if (type == BLACK)
printf(" ○");
if (type == NO)
printf("%s", tableline);
}
打印棋盤的邏輯就是因為沒能設置光標坐標那就只有一行一行打印然后根據(jù)邊界行列值來判斷。 如果要看如何打印改變光標可以參考這篇文章win32 API
void initMap(int map[N + 1][N + 1])
{
//第一行和第一列顯示數(shù)字
for (int i = 0; i < N + 1; i++)
{
map[0][i] = i;
map[i][0] = i;
if (i >= 10)
{
map[0][i] = i - 10;
map[i][0] = i - 10;
}
}
for (int i = 0; i < N + 1; i++)
{
//打印第一行數(shù)字
if (i == 0)
{
for (int j = 0; j < N + 1; j++)
{
printf("%-2d", map[0][j]);
}
printf("\n");
}
//打印第一行棋盤
else if (i == 1)
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┏");
else if (j == N)
draw_chessman(map[i][j], "━┓");
else
draw_chessman(map[i][j], "━┳");
}
printf("\n");
}
//打印最后一行
else if (i == N)
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┗");
else if (j == N)
draw_chessman(map[i][j], "━┛");
else
draw_chessman(map[i][j], "━┻");
}
printf("\n");
}
else
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┣");
else if (j == N)
draw_chessman(map[i][j], "━┫");
else
draw_chessman(map[i][j], "━╋");
}
printf("\n");
}
}
}
人人對戰(zhàn)
人人對戰(zhàn)邏輯中就是先讓黑方下棋,輸入坐標,輸入錯誤就再次輸入(死循環(huán)實現(xiàn)),將該坐標的二維數(shù)組值變?yōu)楹冢缓笞屍溥x擇悔不悔棋,我實現(xiàn)的是只要1是悔棋其他數(shù)字就是不悔棋。執(zhí)行完不悔棋后就判斷是否勝利,如果勝就跳出選擇是否重來一局,如果沒勝就白棋下執(zhí)行相同邏輯。
落子判空函數(shù)
在這個函數(shù)中判斷坐標代表的二維數(shù)組值是不是空,不是就重新輸入坐標。
void judgeEmpty(int map[][N + 1], int x, int y, int goal)
{
while (1)
{
if (map[x][y] != NO)
{
printf("已有棋子,重新輸入\n");
scanf("%d%d", &x, &y);
}
else
{
map[x][y] = goal;
initMap(map);
break;
}
}
}
悔棋函數(shù)
該函數(shù)里面就是根據(jù)用戶選擇,如果悔棋然后將剛才的地方的數(shù)組值變回空。
int retract(int map[][N + 1], int x, int y)
{
int choice = -1;
printf("是否悔棋:是1\n");
scanf("%d", &choice);
if (choice == 1)
{
map[x][y] = NO;
initMap(map);
}
return choice;
}
執(zhí)行完不悔棋后就判斷是否勝利
判勝負函數(shù)
這個函數(shù)就是將下的這個棋子的橫豎斜方向判勝負。(沒有判斷和棋情況),如果要判斷就是二維數(shù)組全不為空狀態(tài),使用遍歷判斷就行。
int judgeWin(int map[][N + 1], int x, int y)
{
for (int i = 1; i < N + 1; i++)
{
for (int j = 1; j < N + 1; j++)
{
if (j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//橫
{
if (map[i][j] == map[i][j + 1]
&& map[i][j + 1] == map[i][j + 2]
&& map[i][j + 2] == map[i][j + 3]
&& map[i][j + 3] == map[i][j + 4])
return map[i][j];
}
if (i < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//豎
{
if (map[i][j] == map[i + 1][j]
&& map[i + 1][j] == map[i + 2][j]
&& map[i + 2][j] == map[i + 3][j]
&& map[i + 3][j] == map[i + 4][j])
return map[i][j];
}
if (i < N + 1 - 4 && j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右下_
{
if (map[i][j] == map[i + 1][j + 1]
&& map[i + 1][j + 1] == map[i + 2][j + 2]
&& map[i + 2][j + 2] == map[i + 3][j + 3]
&& map[i + 3][j + 3] == map[i + 4][j + 4])
return map[i][j];
}
if (i > 4 && j > 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右上
{
if (map[i][j] == map[i - 1][j - 1]
&& map[i - 1][j - 1] == map[i - 2][j - 2]
&& map[i - 2][j - 2] == map[i - 3][j - 3]
&& map[i - 3][j - 3] == map[i - 4][j - 4])
return map[i][j];
}
}
}
return NO;
}
人人對戰(zhàn)
void peopleFight(int map[][N + 1])
{
printf("--------人-人對戰(zhàn)---------------\n");
initMap(map);
while (1)
{
int x = -1;
int y = -1;
black:
while (1)
{
printf("黑方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, BLACK);
if (retract(map, x, y) == 1)
goto black;
//判斷勝利
int ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
white:
while (1)
{
printf("白方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, WHITE);
if (retract(map, x, y) == 1)
goto white;
//判斷勝利
ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
}
}
人機對戰(zhàn)
在這個函數(shù)中用戶選擇落子方,然后執(zhí)行邏輯與人人對戰(zhàn)一樣。 但是電腦生成棋子提供兩種選擇:
一是將直接調(diào)用rand生成隨機值,這就不可控
方法一這樣寫對棋子的位置生成是很不可控的,會讓機器隨機亂落子。
void machine(int map[][N + 1])
{
printf("--------人-機對戰(zhàn)---------------\n");
srand(time(NULL));
int choice = -1;
printf("請輸入你執(zhí)黑棋還是白棋,黑1,白2\n");
scanf("%d", &choice);
if (choice == 1)
{
while (1)
{
int x = -1;
int y = -1;
black:
while (1)
{
printf("黑方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, BLACK);
//判斷勝利
int ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
if (retract(map, x, y) == 1)
goto black;
next:
x = rand() % 15 + 1;
y = rand() % 15 + 1;
if (map[x][y] != NO)
goto next;
judgeEmpty(map, x, y, WHITE);
//判斷勝利
ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
}
}
else if (choice == 2)
{
while (1)
{
int x = -1;
int y = -1;
next2:
x = rand() % 15 + 1;
y = rand() % 15 + 1;
if (map[x][y] != NO)
goto next2;
judgeEmpty(map, x, y, BLACK);
//判斷勝利
int ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
white:
while (1)
{
printf("白方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, WHITE);
//判斷勝利
ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
if (retract(map, x, y) == 1)
goto white;
}
}
}
二是根據(jù)棋子贏面來判斷哪里落子最好
這樣實現(xiàn)就會讓機器落子一直是去圍堵你的棋子,雖然還是很垃圾,但是比方法一好多了。
void AIjudge(int color, int map[N+1][N+1])
{
int num = 1, left = 0, right = 0;
int n, m, score = 0, max = 0;
int dx, dy;
for (int i = 1; i < N+1; i++)
{
for (int j = 1; j < N+1; j++)
{
score = 0;
if (map[i][j] != 0)
continue;
else
{
dx = 1, dy = 0, n = i, m = j;
while (1)//水平向右
{
n += dx, m += dy;
if (map[n][m] == 0)
{
right = 0; break;
}
else if (map[n][m] != color || n > 15)
{
right++; break;
}
else if (num < 5) { num++; }
}
dx = -1, dy = 0;
while (1) {//水平向左
n += dx; m += dy;
if (map[n][m] == 0) { left = 0; break; }
else if (map[n][m] != color || n < 1) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);//用data來算分數(shù),并用score來記錄
// |方向
num = 1; right = 0, left = 0;//每一次改變方向要重置這些變量
dx = 0; dy = -1; n = i; m = j;
//向上
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { left = 0; break; }
else if (map[n][m] != color || m < 1) { left++; break; }
else if (num < 5) { num++; }
}
//向下
dx = 0; dy = 1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || m > 15) { right++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
// \方向
num = 1; right = 0, left = 0;
dx = 1; dy = 1; n = i; m = j;
//向右下
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || m > 15 || n > 15) { right++; break; }
else if (num < 5) { num++; }
}
//向左上
dx = -1; dy = -1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }
else if ((n > 0 && m > 0 && map[n][m] != color) || m < 1 || n < 1) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
// /方向`
num = 1; right = 0, left = 0;
dx = 1; dy = -1; n = i; m = j;
//向右上
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || n > 15 || m < 1) { right++; break; }
else if (num < 5) { num++; }
}
//向左下
dx = -1; dy = 1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }
else if ((n > 0 && m > 0 && map[n][m] != color) || n < 1 || m > 15) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
if (score > max) {//每一次用max保存分數(shù),下一次比較,最后找出最大值
max = score;
position[0] = i;//用來保存每一次的位置和分數(shù)
position[1] = j;
position[2] = score;
}
}
}
}
}
int Data(int num, int count)
{
switch (num)
{
case 1: if (count == 0)//活一:表示在該處落子,就只有這一個棋子,兩邊都沒有阻擋(邊界或對方的棋子)優(yōu)勢較大
return 2;
else if (count == 1)//沖一:表示在該處落子,就只有這一個棋子,兩邊有一種阻擋(邊界或對方的棋子)優(yōu)勢較小
return 1;
else return 0;
break;
case 2:
if (count == 0)//活二;接下來都同理活一和沖一
return 20;
else if (count == 1)//沖二
return 10;
else return 0;
break;
case 3:
if (count == 0)//活三
return 300;
else if (count == 1)//沖三
return 50;
else return 0;
break;
case 4:
if (count == 0)//活四
return 4000;
else if (count == 1)//沖四
return 1000;
else return 0;
break;
case 5://五
return 5000;
break;
default:
return 0;
break;
}
}
void machine(int map[][N + 1])
{
printf("--------人-機對戰(zhàn)---------------\n");
int choice = -1;
do {
printf("請輸入你執(zhí)黑棋還是白棋,黑1,白2\n");
scanf("%d", &choice);
} while (choice != 1 && choice != 2);
initMap(map);
if (choice == 1)
{
while (1)
{
int x = -1;
int y = -1;
black:
while (1)
{
printf("黑方落子\n");
printf("現(xiàn)在棋盤為%d*%d請輸入要落下的坐標x y\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, BLACK);
if (retract(map, x, y))
{
map[x][y] = 0;
initMap(map);
goto black;
}
int ret = judgeWin(map, x, y);
if (ret == BLACK) //判斷勝利
break;
int old_max = 0, new_max = 0, n = 0, m = 0;
int AIx = -1, AIy = -1;
AIjudge(1, map);//判斷黑子的優(yōu)勢位置
old_max = position[2];//保存該位置分數(shù)
AIx = position[0]; AIy = position[1];//保存該位置的坐標,注意行列和xy軸的對應關系
position[0] = 0, position[1] = 0, position[2] = 0;
AIjudge(-1, map);//判斷白子的優(yōu)勢位置
new_max = position[2];//保存分數(shù)
if (new_max >= old_max) //判斷哪個位置的分數(shù)大,從而判斷是堵截還是進攻
{
AIx = position[0]; AIy = position[1];
}
judgeEmpty(map, AIx, AIy, WHITE);
ret = judgeWin(map, x, y);
if (ret == WHITE) //判斷勝利
break;
}
}
else if (choice == 2)
{
while (1)
{
int x = -1, y = -1;
int old_max = 0, new_max = 0, n = 0, m = 0;
int AIx = -1, AIy = -1;
AIjudge(1, map);//判斷黑子的優(yōu)勢位置
old_max = position[2];//保存該位置分數(shù)
AIx = position[0]; AIy = position[1];//保存該位置的坐標,注意行列和xy軸的對應關系
position[0] = 0, position[1] = 0, position[2] = 0;
AIjudge(-1, map);//判斷白子的優(yōu)勢位置
new_max = position[2];//保存分數(shù)
if (new_max >= old_max) //判斷哪個位置的分數(shù)大,從而判斷是堵截還是進攻
{
AIx = position[0]; AIy = position[1];
}
judgeEmpty(map, AIx, AIy, BLACK);
int ret = judgeWin(map, x, y);
if (ret == BLACK) //判斷勝利
break;
white:
while (1)
{
printf("白方落子\n");
printf("現(xiàn)在棋盤為%d*%d請輸入要落下的坐標x y\n", N, N);
scanf("%d,%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, WHITE);
if (retract(map, x, y))
{
map[x][y] = 0;
initMap(map);
goto white;
}
ret = judgeWin(map, x, y);
if (ret == WHITE) //判斷勝利
break;
}
}
}
如果選擇退出程序直接exit就行
主函數(shù)調(diào)用邏輯
用死循環(huán)調(diào)用,然后根據(jù)menu返回值通過switch-case來調(diào)用相應模式函數(shù),最后在讓用戶選擇是否再來一局,如果再來一局就不出循環(huán),不再來就出循環(huán)。
int main()
{
while (1)
{
int map[N + 1][N + 1] = { 0 };
int choice = menu();
switch (choice)
{
case 1:
//調(diào)用人人對打
peopleFight(map);
break;
case 2:
//調(diào)用人機對打
machine(map);
break;
case 0:
printf("退出成功\n");
exit(0);
break;
}
int a = 0;
printf("是否再來一盤:是1,不是0\n");
scanf("%d", &a);
if (a == 0)
break;
}
return 0;
}
源代碼
源碼呈上,為方便復制寫在同一個文件之下,可以多文件進行。
# define _CRT_SECURE_NO_WARNINGS 1;
#include
#include
#include
#define N 15 //表示棋盤的行列
#define NO 0 //表示沒下子的狀態(tài)
#define BLACK 1
#define WHITE -1
//棋盤初始化函數(shù)
void initMap(int map[N + 1][N + 1]);
//落子函數(shù)
void judgeEmpty(int map[][N + 1], int x, int y, int goal);
//人人對打
void peopleFight(int map[][N + 1]);
//判斷勝利
int judgeWin(int map[][N + 1], int x, int y);
//悔棋
int retract(int map[][N + 1], int x, int y);
//人機對打
void machine(int map[][N + 1]);
//打印菜單并返回選擇的模式
int menu();
void AIjudge(int color, int map[N + 1][N + 1]);
int Data(int num, int count);
int position[3];
int main()
{
while (1)
{
int map[N + 1][N + 1] = { 0 };
int choice = menu();
switch (choice)
{
case 1:
//調(diào)用人人對打
peopleFight(map);
break;
case 2:
//調(diào)用人機對打
machine(map);
break;
case 0:
printf("退出成功\n");
exit(0);
break;
}
int a = 0;
printf("是否再來一盤:是1,不是0\n");
scanf("%d", &a);
if (a == 0)
break;
}
return 0;
}
int menu()
{
int choice = -1;
while (1)
{
printf("----------------歡迎使用五子棋------------------------\n");
printf("- 請選擇模式 -\n");
printf("- 1.人-人對戰(zhàn)游戲 -\n");
printf("- 2.人-機對戰(zhàn)游戲 -\n");
printf("- 0.退出游戲 -\n");
printf("------------------------------------------------------\n");
printf("------------------------------------------------------\n");
scanf("%d", &choice);
if (choice > 4 || choice < 0)
printf("錯誤輸入");
else
break;
}
return choice;
}
void judgeEmpty(int map[][N + 1], int x, int y, int goal)
{
while (1)
{
if (map[x][y] != NO)
{
printf("已有棋子,重新輸入\n");
scanf("%d%d", &x, &y);
}
else
{
map[x][y] = goal;
initMap(map);
break;
}
}
}
int judgeWin(int map[][N + 1], int x, int y)
{
for (int i = 1; i < N + 1; i++)
{
for (int j = 1; j < N + 1; j++)
{
if (j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//橫
{
if (map[i][j] == map[i][j + 1]
&& map[i][j + 1] == map[i][j + 2]
&& map[i][j + 2] == map[i][j + 3]
&& map[i][j + 3] == map[i][j + 4])
return map[i][j];
}
if (i < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//豎
{
if (map[i][j] == map[i + 1][j]
&& map[i + 1][j] == map[i + 2][j]
&& map[i + 2][j] == map[i + 3][j]
&& map[i + 3][j] == map[i + 4][j])
return map[i][j];
}
if (i < N + 1 - 4 && j < N + 1 - 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右下_
{
if (map[i][j] == map[i + 1][j + 1]
&& map[i + 1][j + 1] == map[i + 2][j + 2]
&& map[i + 2][j + 2] == map[i + 3][j + 3]
&& map[i + 3][j + 3] == map[i + 4][j + 4])
return map[i][j];
}
if (i > 4 && j > 4 && (map[i][j] == BLACK || map[i][j] == WHITE))//右上
{
if (map[i][j] == map[i - 1][j - 1]
&& map[i - 1][j - 1] == map[i - 2][j - 2]
&& map[i - 2][j - 2] == map[i - 3][j - 3]
&& map[i - 3][j - 3] == map[i - 4][j - 4])
return map[i][j];
}
}
}
return NO;
}
//繪制棋子
void draw_chessman(int type, char* tableline) {
if (type == WHITE)
printf(" ●");
if (type == BLACK)
printf(" ○");
if (type == NO)
printf("%s", tableline);
}
void initMap(int map[N + 1][N + 1])
{
//第一行和第一列顯示數(shù)字
for (int i = 0; i < N + 1; i++)
{
map[0][i] = i;
map[i][0] = i;
if (i >= 10)
{
map[0][i] = i - 10;
map[i][0] = i - 10;
}
}
for (int i = 0; i < N + 1; i++)
{
//打印第一行數(shù)字
if (i == 0)
{
for (int j = 0; j < N + 1; j++)
{
printf("%-2d", map[0][j]);
}
printf("\n");
}
//打印第一行棋盤
else if (i == 1)
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┏");
else if (j == N)
draw_chessman(map[i][j], "━┓");
else
draw_chessman(map[i][j], "━┳");
}
printf("\n");
}
//打印最后一行
else if (i == N)
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┗");
else if (j == N)
draw_chessman(map[i][j], "━┛");
else
draw_chessman(map[i][j], "━┻");
}
printf("\n");
}
else
{
for (int j = 0; j < N + 1; j++)
{
if (j == 0)
printf("%d", map[i][j]);
else if (j == 1)
draw_chessman(map[i][j], " ┣");
else if (j == N)
draw_chessman(map[i][j], "━┫");
else
draw_chessman(map[i][j], "━╋");
}
printf("\n");
}
}
}
//void machine(int map[][N + 1])
//{
// printf("--------人-機對戰(zhàn)---------------\n");
// srand(time(NULL));
// int choice = -1;
// printf("請輸入你執(zhí)黑棋還是白棋,黑1,白2\n");
// scanf("%d", &choice);
// if (choice == 1)
// {
// while (1)
// {
// int x = -1;
// int y = -1;
// black:
// while (1)
// {
// printf("黑方落子\n");
// printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
// scanf("%d%d", &x, &y);
// if (x < 0 || x > N || y < 0 || y > N)
// printf("錯誤輸入\n");
// else
// break;
// }
// judgeEmpty(map, x, y, BLACK);
// //判斷勝利
// int ret = judgeWin(map, x, y);
// if (ret == BLACK)
// {
// printf("黑方獲勝\n");
// return;
// }
// else if (ret == WHITE)
// {
// printf("白方獲勝\n");
// return;
// }
// if (retract(map, x, y) == 1)
// goto black;
// next:
// x = rand() % 15 + 1;
// y = rand() % 15 + 1;
// if (map[x][y] != NO)
// goto next;
// judgeEmpty(map, x, y, WHITE);
// //判斷勝利
// ret = judgeWin(map, x, y);
// if (ret == BLACK)
// {
// printf("黑方獲勝\n");
// return;
// }
// else if (ret == WHITE)
// {
// printf("白方獲勝\n");
// return;
// }
// }
// }
// else if (choice == 2)
// {
// while (1)
// {
// int x = -1;
// int y = -1;
// next2:
// x = rand() % 15 + 1;
// y = rand() % 15 + 1;
// if (map[x][y] != NO)
// goto next2;
// judgeEmpty(map, x, y, BLACK);
// //判斷勝利
// int ret = judgeWin(map, x, y);
// if (ret == BLACK)
// {
// printf("黑方獲勝\n");
// return;
// }
// else if (ret == WHITE)
// {
// printf("白方獲勝\n");
// return;
// }
// white:
// while (1)
// {
// printf("白方落子\n");
// printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
// scanf("%d%d", &x, &y);
// if (x < 0 || x > N || y < 0 || y > N)
// printf("錯誤輸入\n");
// else
// break;
// }
// judgeEmpty(map, x, y, WHITE);
// //判斷勝利
// ret = judgeWin(map, x, y);
// if (ret == BLACK)
// {
// printf("黑方獲勝\n");
// return;
// }
// else if (ret == WHITE)
// {
// printf("白方獲勝\n");
// return;
// }
// if (retract(map, x, y) == 1)
// goto white;
//
// }
// }
//
//}
void peopleFight(int map[][N + 1])
{
printf("--------人-人對戰(zhàn)---------------\n");
initMap(map);
while (1)
{
int x = -1;
int y = -1;
black:
while (1)
{
printf("黑方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, BLACK);
if (retract(map, x, y) == 1)
goto black;
//判斷勝利
int ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
white:
while (1)
{
printf("白方落子\n");
printf("請輸入要落下的坐標現(xiàn)在棋盤為%d*%d\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, WHITE);
if (retract(map, x, y) == 1)
goto white;
//判斷勝利
ret = judgeWin(map, x, y);
if (ret == BLACK)
{
printf("黑方獲勝\n");
return;
}
else if (ret == WHITE)
{
printf("白方獲勝\n");
return;
}
}
}
int retract(int map[][N + 1], int x, int y)
{
int choice = -1;
printf("是否悔棋:是1\n");
scanf("%d", &choice);
if (choice == 1)
{
map[x][y] = NO;
initMap(map);
}
return choice;
}
void AIjudge(int color, int map[N+1][N+1])
{
int num = 1, left = 0, right = 0;
int n, m, score = 0, max = 0;
int dx, dy;
for (int i = 1; i < N+1; i++)
{
for (int j = 1; j < N+1; j++)
{
score = 0;
if (map[i][j] != 0)
continue;
else
{
dx = 1, dy = 0, n = i, m = j;
while (1)//水平向右
{
n += dx, m += dy;
if (map[n][m] == 0)
{
right = 0; break;
}
else if (map[n][m] != color || n > 15)
{
right++; break;
}
else if (num < 5) { num++; }
}
dx = -1, dy = 0;
while (1) {//水平向左
n += dx; m += dy;
if (map[n][m] == 0) { left = 0; break; }
else if (map[n][m] != color || n < 1) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);//用data來算分數(shù),并用score來記錄
// |方向
num = 1; right = 0, left = 0;//每一次改變方向要重置這些變量
dx = 0; dy = -1; n = i; m = j;
//向上
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { left = 0; break; }
else if (map[n][m] != color || m < 1) { left++; break; }
else if (num < 5) { num++; }
}
//向下
dx = 0; dy = 1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || m > 15) { right++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
// \方向
num = 1; right = 0, left = 0;
dx = 1; dy = 1; n = i; m = j;
//向右下
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || m > 15 || n > 15) { right++; break; }
else if (num < 5) { num++; }
}
//向左上
dx = -1; dy = -1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }
else if ((n > 0 && m > 0 && map[n][m] != color) || m < 1 || n < 1) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
// /方向`
num = 1; right = 0, left = 0;
dx = 1; dy = -1; n = i; m = j;
//向右上
while (1) {
n += dx; m += dy;
if (map[n][m] == 0) { right = 0; break; }
else if (map[n][m] != color || n > 15 || m < 1) { right++; break; }
else if (num < 5) { num++; }
}
//向左下
dx = -1; dy = 1; n = i; m = j;
while (1) {
n += dx; m += dy;
if (n > 0 && m > 0 && map[n][m] == 0) { left = 0; break; }
else if ((n > 0 && m > 0 && map[n][m] != color) || n < 1 || m > 15) { left++; break; }
else if (num < 5) { num++; }
}
score += Data(num, right + left);
if (score > max) {//每一次用max保存分數(shù),下一次比較,最后找出最大值
max = score;
position[0] = i;//用來保存每一次的位置和分數(shù)
position[1] = j;
position[2] = score;
}
}
}
}
}
int Data(int num, int count)
{
switch (num)
{
case 1: if (count == 0)//活一:表示在該處落子,就只有這一個棋子,兩邊都沒有阻擋(邊界或對方的棋子)優(yōu)勢較大
return 2;
else if (count == 1)//沖一:表示在該處落子,就只有這一個棋子,兩邊有一種阻擋(邊界或對方的棋子)優(yōu)勢較小
return 1;
else return 0;
break;
case 2:
if (count == 0)//活二;接下來都同理活一和沖一
return 20;
else if (count == 1)//沖二
return 10;
else return 0;
break;
case 3:
if (count == 0)//活三
return 300;
else if (count == 1)//沖三
return 50;
else return 0;
break;
case 4:
if (count == 0)//活四
return 4000;
else if (count == 1)//沖四
return 1000;
else return 0;
break;
case 5://五
return 5000;
break;
default:
return 0;
break;
}
}
void machine(int map[][N + 1])
{
printf("--------人-機對戰(zhàn)---------------\n");
int choice = -1;
do {
printf("請輸入你執(zhí)黑棋還是白棋,黑1,白2\n");
scanf("%d", &choice);
} while (choice != 1 && choice != 2);
initMap(map);
if (choice == 1)
{
while (1)
{
int x = -1;
int y = -1;
black:
while (1)
{
printf("黑方落子\n");
printf("現(xiàn)在棋盤為%d*%d請輸入要落下的坐標x y\n", N, N);
scanf("%d%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, BLACK);
if (retract(map, x, y))
{
map[x][y] = 0;
initMap(map);
goto black;
}
int ret = judgeWin(map, x, y);
if (ret == BLACK) //判斷勝利
break;
int old_max = 0, new_max = 0, n = 0, m = 0;
int AIx = -1, AIy = -1;
AIjudge(1, map);//判斷黑子的優(yōu)勢位置
old_max = position[2];//保存該位置分數(shù)
AIx = position[0]; AIy = position[1];//保存該位置的坐標,注意行列和xy軸的對應關系
position[0] = 0, position[1] = 0, position[2] = 0;
AIjudge(-1, map);//判斷白子的優(yōu)勢位置
new_max = position[2];//保存分數(shù)
if (new_max >= old_max) //判斷哪個位置的分數(shù)大,從而判斷是堵截還是進攻
{
AIx = position[0]; AIy = position[1];
}
judgeEmpty(map, AIx, AIy, WHITE);
ret = judgeWin(map, x, y);
if (ret == WHITE) //判斷勝利
break;
}
}
else if (choice == 2)
{
while (1)
{
int x = -1, y = -1;
int old_max = 0, new_max = 0, n = 0, m = 0;
int AIx = -1, AIy = -1;
AIjudge(1, map);//判斷黑子的優(yōu)勢位置
old_max = position[2];//保存該位置分數(shù)
AIx = position[0]; AIy = position[1];//保存該位置的坐標,注意行列和xy軸的對應關系
position[0] = 0, position[1] = 0, position[2] = 0;
AIjudge(-1, map);//判斷白子的優(yōu)勢位置
new_max = position[2];//保存分數(shù)
if (new_max >= old_max) //判斷哪個位置的分數(shù)大,從而判斷是堵截還是進攻
{
AIx = position[0]; AIy = position[1];
}
judgeEmpty(map, AIx, AIy, BLACK);
int ret = judgeWin(map, x, y);
if (ret == BLACK) //判斷勝利
break;
white:
while (1)
{
printf("白方落子\n");
printf("現(xiàn)在棋盤為%d*%d請輸入要落下的坐標x y\n", N, N);
scanf("%d,%d", &x, &y);
if (x < 0 || x > N || y < 0 || y > N)
printf("錯誤輸入\n");
else
break;
}
judgeEmpty(map, x, y, WHITE);
if (retract(map, x, y))
{
map[x][y] = 0;
initMap(map);
goto white;
}
ret = judgeWin(map, x, y);
if (ret == WHITE) //判斷勝利
break;
}
}
}
柚子快報邀請碼778899分享:【C語言】五子棋(c語言實現(xiàn))
參考文章
本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。