? 五子棋是一个非常经典的游戏,今天我试着用c语言来写,可以自定义多少个子连在一起算是胜利,自定义棋盘大小,不足的是AI只能下随机,没有一定的分析棋盘能力。
? 首先理清楚思路,我希望程序能先打印棋盘,然后让我下棋,之后判断下棋位置的合法性(不合法则提示我重新下),然后判断玩家是否胜利,接着判断平局。机器下则是运用随机数,别的步骤是一样的。
? 思路理清开始写代码,先写一个简单的打印菜单;
void menu()
{
printf("-----------------------------------\n");
printf("******* 1.开始游戏 *********\n");
printf("******* 0.退出游戏 *********\n");
printf("-----------------------------------\n");
int input = 0;
char arr[HANG][LIE] = { 0 };
printf("请选择:");
do
{
scanf("%d", &input);
switch (input)
{
case 1:
game(arr, HANG, LIE);
break;
case 0:
printf("退出");
break;
default:
printf("输入的值错误,请重新输入:");
}
} while (input);
}
然后写出游戏函数
void game(char arr[HANG][LIE],int hang,int lie)
{
chushihua(arr, hang, lie);
display(arr, hang, lie);
while (1)
{
if (put_palyer(arr,hang,lie) == 1)
{
display(arr, hang, lie);
printf("\n玩家赢\n");
break;
}
if (is_full(arr, hang, lie))
{
display(arr, hang, lie);
printf("\n平局\n");
break;
}
display(arr, hang, lie);
if (put_computer(arr,hang,lie) == 1)
{
display(arr, hang, lie);
printf("电脑赢");
break;
}
if (is_full(arr, hang, lie))
{
display(arr, hang, lie);
printf("\n平局\n");
break;
}
display(arr, hang, lie);
}
menu();//我希望结束后玩家能看到上次结束时的完整棋盘,并可以选择是否进行下一次游戏
}
当然数组最好是要初始化一下
void chushihua(char arr[HANG][LIE], int hang, int lie)
{
int i = 0;
int j = 0;
for (i = 0; i < hang; i++)
{
for (j = 0; j < lie; j++)
arr[i][j] = ' ';
}
}
之后写出打印函数,能打印出棋盘
void display(char arr[HANG][LIE], int hang, int lie)
{
system("cls");
int i = 0;
int j = 0;
for (i = 0; i < hang; i++)
printf(" %d ", i + 1);
printf("\n");
for (i = 0; i < hang; i++)
{
printf("%d", i + 1);
for (j = 0; j < lie-1; j++)
{
printf(" %c |", arr[i][j]);
}
printf(" %c\n ", arr[i][j]);
if (i < hang - 1)
{
for (j = 0; j < lie - 1; j++)
printf("---|");
printf("---\n");
}
}
}
接着写出 玩家和计算机下棋的函数
int put_palyer(char arr[HANG][LIE],int hang,int lie)
{
int i = 0;
int j = 0;
printf("(#方)请输入坐标:");
while (1)
{
scanf("%d %d", &i, &j);
if (i < 1 || i > hang || j < 1 || j > lie)
{
printf("坐标非法,重新输入:");
continue;
}
else if (arr[i-1][j-1] != ' ')
{
printf("坐标占用,重新输入:");
continue;
}
else
{
arr[i-1][j-1] = '#';
break;
}
}
if (panduan(arr, hang, lie, '#') == 1)
return 1;
return 0;
}
int put_computer(char arr[HANG][LIE], int hang, int lie)
{
while (1)
{
int i = rand() % hang;
srand((unsigned int)time(NULL));
int j = rand() % lie;
if (0 <= i && i < hang && 0 <= j && j < lie && arr[i][j] == ' ')
{
arr[i][j] = '@';
break;
}
}
if (panduan(arr, hang, lie, '@') == 1)
return 1;
return 0;
}
最后最难的是实现判断输赢的函数
我的思路是4个大判断 分别为竖直 水平 左上到右下 左下到右上 4 个大判断
然后创建一个全局变量flag? 如果在某行 或者 某列 或者 某斜线中 发现有玩家或者电脑下的棋,flag就+1,但是如果没有,就说明被断开了,flag就要变为0,在这一列,或者在这行中,或者在这斜线中,发现flag=5,那么就可以说明玩家或者电脑获胜。非常需要注意的是,换行,换列,换斜线都要重新让flag=0。
知道了判断思路,但是怎么写判断过程呢。竖直和水平是很容易的,难点是斜线判断。这里引入局部变量k,再次将左上到右下,左下到右上分别分为两个部分。
?我们来看左上到右下的过程。分为两个部分。靠上的箭头和靠下的箭头。
从靠下的箭头来讲。我希望用k来表示判断斜线的下移,但是因为五子棋的缘故,所以k最大为hang-5,其中hang为行数。然后就像竖直和水平那样,进行判断,但是每次行都要以k为起始位置。
从靠上的箭头来讲。我希望用k来表示判断斜线的右移。但是因为五子棋的缘故,所以k最低为lie-5,其中lie为列数,然后就和上面的是一样,只不过,k最大为lie-5,列数每次都从k开始。
int panduan2(char x,char y)
{
if (x == y)
flag++;
else
flag = 0;
if (flag == 5)
return 1;
return 0;
}
int panduan(char arr[HANG][LIE], int hang, int lie, char a)
{
int flag = 0;
int i = 0;
int j = 0;
int k = 0;
for (i = 0; i < hang; i++)//横向判断
{
flag = 0;
for (j = 0; j < lie; j++)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
for (j = 0; j < hang; j++)//竖向判断
{
flag = 0;
for (i = 0; i < lie; i++)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
for (k = 0; k < hang - 4; k++)
{
flag = 0;
for (i = k, j = 0; i < hang; i++, j++)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
for (k = 1; k < lie - 4; k++)
{
flag = 0;
for (i = 0, j = k; j < lie; i++, j++)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
for (k = hang - 1; k > 3; k--)
{
flag = 0;
for (i = k, j = 0; i >= 0; i--, j++)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
for (k = 1; k < lie - 4; k++)
{
flag = 0;
for (i = hang - 1, j = k; j < lie; j++, i--)
if (panduan2(arr[i][j], a) == 1)
return 1;
}
return 0;
}
左下到右上也是一样的方法和思路。
最后我们还需要写一个判断平局的代码。
int is_full(char arr[HANG][LIE], int hang, int lie)
{
int i = 0;
int j = 0;
for (i = 0; i < hang; i++)
{
for (j = 0; j < lie; j++)
if (arr[i][j] == ' ')
return 0;
}
return 1;
}
最后完成了整个程序的基本实现逻辑。
gitee链接:RoseIsBlue/learning_c_language - Gitee.com
11.8的代码
|