分析:
整体思路如下:
头文件
#define __GAME_H__
#define ROW 9//棋盘行数
#define COL 9//棋盘列数
#define NUM 5//五子棋
void InitBoard(char board[ROW][COL],int row,int col);
void PrintBoard(char board[ROW][COL],int row,int col);
void Player(char board[ROW][COL],int row,int col);
void Computer(char board[ROW][COL],int row,int col,int num);
char Judge(char board[ROW][COL],int row,int col,int num);
#endif
上述代码中,ROW、COL用来修改棋盘的大小,NUM用来修改要玩的是三子棋还是五子棋还是其它,InitBoard函数用来对棋盘初始化,PrintBoard函数用来打印棋盘,Player函数用来实现玩家选择坐标,Computer函数用来实现电脑选择坐标,Judge函数用来判断输赢情况。
测试程序
void test()
{
int n = 0;
srand((unsigned)time(NULL));
do
{
memu();
printf("请选择:\n");
scanf("%d",&n);
if(n==1)
{
game();
}
else if(n==0)
{
printf("退出游戏\n");
break;
}
else
{
printf("输入错误,请重输:\n");
}
}while(n);
}
int main()
{
test();
return 0;
}
游戏菜单
void memu()
{
printf("********************\n");
printf("**** 1.play ****\n");
printf("**** 0.exit ****\n");
printf("********************\n");
}
游戏执行程序
void game()
{
char c = 0;
char board[ROW][COL];
InitBoard(board,ROW,COL);
PrintBoard(board,ROW,COL);
while(1)
{
printf("玩家走:>\n");
Player(board,ROW,COL);
PrintBoard(board,ROW,COL);
c = Judge(board,ROW,COL,NUM);
if(c!='+')
{
break;
}
printf("电脑走:>\n");
Computer(board,ROW,COL,NUM);
PrintBoard(board,ROW,COL);
c = Judge(board,ROW,COL,NUM);
if(c!='+')
{
break;
}
}
PrintBoard(board,ROW,COL);
if(c=='@')
{
printf("玩家赢\n");
}
else if(c=='O')
{
printf("电脑赢\n");
}
else if(c=='I')
{
printf("平局\n");
}
}
棋盘初始化
void InitBoard(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
board[i][j]='+';
}
}
}
打印棋盘
void PrintBoard(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf(" |");
}
printf("\n");
for(j=0; j<row; j++)
{
printf("-%c",board[i][j]);
}
printf("-\n");
}
for(j=0; j<col; j++)
{
printf(" |");
}
printf("\n");
}
玩家坐标选择
int now_row = 0;//记录当前位置行值
int now_col = 0;//记录当前位置列值
void Player(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
while(1)
{
scanf("%d %d",&i,&j);
now_row = i-1;
now_col = j-1;
if(now_row<row && now_col<col)
{
if(board[now_row][now_col]=='+')
{
board[now_row][now_col]='@';
break;
}
else
{
printf("坐标无效,请重新输入:\n");
}
}
else
{
printf("坐标无效,请重新输入:\n");
}
}
}
电脑坐标
void Computer(char board[ROW][COL],int row,int col,int num)
{
int i = 0;
int j = 0;
int count = 0;
char c = board[now_row][now_col];
int a = 0;
int b = 0;
int ret = num-2;
while(1)
{
//当前位置行的右判断
if((now_col<col-ret)&&(now_col >=1))
{
for(a= now_row,b= now_col; b<now_col+ret; b++)
{
if(board[a][b] != c)
{
break;
}
}
if(b == now_col+ret)
{
if(board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if(board[a][b-ret-1] == '+')
{
board[a][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置行的左判断
if((now_col >= ret) && (now_col < col-1))
{
for(a = now_row, b = now_col; b > now_col-ret; b--)
{
if(board[a][b] != c)
{
break;
}
}
if(b == now_col-ret)
{
if(board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if(board[a][b+ret+1] == '+')
{
board[a][b+ret+1] = 'O';
goto exit;
}
}
}
//当前位置列的上判断
if ((now_row >= ret) && (now_row < col - 1))
{
for (a = now_row, b = now_col; a > now_row-ret; a--)
{
if (board[a][b] != c)
{
break;
}
}
if (a == now_row-ret)
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b] == '+')
{
board[a+ret+1][b] = 'O';
goto exit;
}
}
}
//当前位置列的下判断
if ((now_row<col - ret) && (now_row >= 1))
{
for (a = now_row, b = now_col; a < now_col+ret; a++)
{
if (board[a][b] != c)
{
break;
}
}
if (a == now_row + ret)
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a-ret-1][b] == '+')
{
board[a-ret-1][b] = 'O';
goto exit;
}
}
}
//当前位置右下对角线的判断
if ((now_row < row-ret) && (now_col < col-ret) && (now_row >= 1) && (now_col >= 1))
{
for (a = now_row, b = now_col; a<now_row+ret && b<now_col+ret; a++, b++)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row+ret) && (b == now_col+ret))
{
if (board[a][b] == '+')
{
board[a][b] = '0';
goto exit;
}
else if (board[a-ret-1][b-ret-1] == '+')
{
board[a-ret-1][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置左下对角线的判断
if ((now_row < row-ret) && (now_col >= ret) && (now_row >= 1) && (now_col < col-1))
{
for (a = now_row, b = now_col; a<now_row+ret && b>now_col-ret; a++, b--)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row+ret) && (b == now_col-ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a-ret-1][b+ret+1] == '+')
{
board[a-ret-1][b+ret+1] = 'O';
goto exit;
}
}
}
//当前位置右上对角线的判断
if ((now_row >= ret) && (now_col < row-ret) && (now_row < row-1) && (now_col >= 1))
{
for (a = now_row, b = now_col; a > now_row-ret && b < now_col+ret; a--, b++)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row-ret) && (b == now_col+ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b-ret-1] == '+')
{
board[a+ret+1][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置左上对角线的判断
if ((now_row >= ret) && (now_col >= ret) && (now_row < row-1) && (now_col < col-1))
{
for (a = now_row, b = now_col; a > now_row-ret && b > now_col-ret; a--, b--)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row-ret) && (b == now_col-ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b+ret+1] == '+')
{
board[a+ret+1][b+ret+1] = 'O';
goto exit;
}
}
}
i = rand() % row;
j = rand() % row;
if (board[i][j] == '+')
{
board[i][j] = 'O';
goto exit;
//break;
}
}
exit:;
}
在此函数中,对电脑所走位置的选择稍微进行了优化,拿一个9行9列棋盘的五子棋来举例,它在内存中的存储如下图所示:
通过记录玩家所走的当前位置,在此函数中用当前位置来确定电脑要走的位置。
1、首先要对当前位置的右侧进行判断,若当前位置的右侧两位和当前位置的字符相同,应将三个位置的左侧或右侧堵上。(当前位置应在合理范围内)如下图所示:当前位置在15处,判断15右侧的16和17是否与15相等,若相等,若14处没有放子,放置14处,若18没有放子,放置18处。
2、用同上方法对当前位置的左侧进行判断。
3、其次判断当前位置的上方。(当前位置应在合理范围内)如下图所示:当前位置在32处,判断32上方的12和22是否与32相等,若相等,若02处没有放子,放置02处,若42处没有放子,放置42处。
4、用同上方法对当前位置的下方进行判断。
5、最后分别对当前位置的对角线右下、左下、右上、左上方进行判断。(当前位置应在合理范围内)如下图所示:当前位置在55处,判断55右下方对角线的66和77是否与55相等,若相等,若88处没有放子,放置88处,若44处没有放子,放置44处。
判断输赢结果
char Judge(char board[ROW][COL],int row,int col,int num)
{
int i = 0;
int j = 0;
char ret = 0;
char c = 0;
int a = 0;
int b = 0;
int n = num-1;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
if(board[i][j]!='+')
{
c = board[i][j];
//判断行
if(j<col-n)
{
for(a=i,b=j; b<=j+n; b++)
{
if(board[a][b]!=c)
{
break;
}
}
if((b>j+n))
{
return c;
}
}
//判断列
if(i<row-n)
{
for(a=i,b=j; a<=i+n; a++)
{
if(board[a][b]!=c)
{
break;
}
}
if((a>i+n))
{
return c;
}
}
//判断对角线
//判断右下对角线
if((i<row-n)&&(j<col-n))
{
for(a=i,b=j; (a<=i+n) && (b<=j+n);a++,b++)
{
if(board[a][b]!=c)
{
break;
}
if((a>i+n)&&(b>j+n))
{
return c;
}
}
}
//判断左下对角线
if((i<row-n)&&(j>=n))
{
for(a=i,b=j; (a<=i+n) && (b>=j-n); a++,b--)
{
if(board[a][b]!=c)
{
break;
}
}
if((a>i+n)&&(b<j-n))
{
return c;
}
}
//判断右上对角线
if((i>=n)&&(j<col-n))
{
for(a=i,b=j; (a>=i-n) && (b<=j+n); a--,b++)
{
if(board[a][b]!=c)
{
break;
}
}
if((a<i-n)&&(b>j+n))
{
return c;
}
}
//判断左上对角线
if((i>=n)&&(j>=n))
{
for(a=i,b=j; (a>=i-n) && (b>=j-n); a--,b--)
{
if(board[a][b]!=c)
{
break;
}
}
if((a<i-n)&&(b<j-n))
{
return c;
}
}
}
}
}
//判断是否平局
ret = Isfull(board,ROW,COL);
if(ret=='I')
{
return 'I';
}
return '+';
}
char Isfull(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
if(board[i][j]=='+')
{
return '+';
}
}
}
if(i==row && j==col)
{
return 'I';
}
}
在此函数中,如果这个位置不与初始值相等,则判断它的行、列、对角线来确定是否达到五子连珠要求,如果达到,返回当前位置的字符,判断输赢,如果都不满足,则应通过棋盘是否满子来确定是否平局。
整体代码
game.h
#ifndef __GAME_H__
#define __GAME_H__
#define ROW 9
#define COL 9
#define NUM 5
void InitBoard(char board[ROW][COL],int row,int col);
void PrintBoard(char board[ROW][COL],int row,int col);
void Player(char board[ROW][COL],int row,int col);
void Computer(char board[ROW][COL],int row,int col,int num);
char Judge(char board[ROW][COL],int row,int col,int num);
#endif
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "sanziqi.h"
#include <time.h>
#include <stdlib.h>
void game()
{
char c = 0;
char board[ROW][COL];
InitBoard(board,ROW,COL);
PrintBoard(board,ROW,COL);
while(1)
{
printf("玩家走:>\n");
Player(board,ROW,COL);
PrintBoard(board,ROW,COL);
c = Judge(board,ROW,COL,NUM);
if(c!='+')
{
break;
}
printf("电脑走:>\n");
Computer(board,ROW,COL,NUM);
PrintBoard(board,ROW,COL);
c = Judge(board,ROW,COL,NUM);
if(c!='+')
{
break;
}
}
PrintBoard(board,ROW,COL);
if(c=='@')
{
printf("玩家赢\n");
}
else if(c=='O')
{
printf("电脑赢\n");
}
else if(c=='I')
{
printf("平局\n");
}
}
void memu()
{
printf("********************\n");
printf("**** 1.play ****\n");
printf("**** 0.exit ****\n");
printf("********************\n");
}
void test()
{
int n = 0;
srand((unsigned)time(NULL));
do
{
memu();
printf("请选择:\n");
scanf("%d",&n);
if(n==1)
{
game();
}
else if(n==0)
{
printf("退出游戏\n");
break;
}
else
{
printf("输入错误,请重输:\n");
}
}while(n);
}
int main()
{
test();
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include "sanziqi.h"
char Isfull(char board[ROW][COL],int row,int col);
void InitBoard(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
board[i][j]='+';
}
}
}
void PrintBoard(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf(" |");
}
printf("\n");
for(j=0; j<row; j++)
{
printf("-%c",board[i][j]);
}
printf("-\n");
}
for(j=0; j<col; j++)
{
printf(" |");
}
printf("\n");
}
int now_row = 0;
int now_col = 0;
void Player(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
while(1)
{
scanf("%d %d",&i,&j);
now_row = i-1;
now_col = j-1;
if(now_row<row && now_col<col)
{
if(board[now_row][now_col]=='+')
{
board[now_row][now_col]='@';
break;
}
else
{
printf("坐标无效,请重新输入:\n");
}
}
else
{
printf("坐标无效,请重新输入:\n");
}
}
}
void Computer(char board[ROW][COL],int row,int col,int num)
{
int i = 0;
int j = 0;
int count = 0;
char c = board[now_row][now_col];
int a = 0;
int b = 0;
int ret = num-2;
while(1)
{
//当前位置行的右判断
if((now_col<col-ret)&&(now_col >=1))
{
for(a= now_row,b= now_col; b<now_col+ret; b++)
{
if(board[a][b] != c)
{
break;
}
}
if(b == now_col+ret)
{
if(board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if(board[a][b-ret-1] == '+')
{
board[a][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置行的左判断
if((now_col >= ret) && (now_col < col-1))
{
for(a = now_row, b = now_col; b > now_col-ret; b--)
{
if(board[a][b] != c)
{
break;
}
}
if(b == now_col-ret)
{
if(board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if(board[a][b+ret+1] == '+')
{
board[a][b+ret+1] = 'O';
goto exit;
}
}
}
//当前位置列的上判断
if ((now_row >= ret) && (now_row < col - 1))
{
for (a = now_row, b = now_col; a > now_row-ret; a--)
{
if (board[a][b] != c)
{
break;
}
}
if (a == now_row-ret)
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b] == '+')
{
board[a+ret+1][b] = 'O';
goto exit;
}
}
}
//当前位置列的下判断
if ((now_row<col - ret) && (now_row >= 1))
{
for (a = now_row, b = now_col; a < now_col+ret; a++)
{
if (board[a][b] != c)
{
break;
}
}
if (a == now_row + ret)
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a-ret-1][b] == '+')
{
board[a-ret-1][b] = 'O';
goto exit;
}
}
}
//当前位置右下对角线的判断
if ((now_row < row-ret) && (now_col < col-ret) && (now_row >= 1) && (now_col >= 1))
{
for (a = now_row, b = now_col; a<now_row+ret && b<now_col+ret; a++, b++)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row+ret) && (b == now_col+ret))
{
if (board[a][b] == '+')
{
board[a][b] = '0';
goto exit;
}
else if (board[a-ret-1][b-ret-1] == '+')
{
board[a-ret-1][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置左下对角线的判断
if ((now_row < row-ret) && (now_col >= ret) && (now_row >= 1) && (now_col < col-1))
{
for (a = now_row, b = now_col; a<now_row+ret && b>now_col-ret; a++, b--)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row+ret) && (b == now_col-ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a-ret-1][b+ret+1] == '+')
{
board[a-ret-1][b+ret+1] = 'O';
goto exit;
}
}
}
//当前位置右上对角线的判断
if ((now_row >= ret) && (now_col < row-ret) && (now_row < row-1) && (now_col >= 1))
{
for (a = now_row, b = now_col; a > now_row-ret && b < now_col+ret; a--, b++)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row-ret) && (b == now_col+ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b-ret-1] == '+')
{
board[a+ret+1][b-ret-1] = 'O';
goto exit;
}
}
}
//当前位置左上对角线的判断
if ((now_row >= ret) && (now_col >= ret) && (now_row < row-1) && (now_col < col-1))
{
for (a = now_row, b = now_col; a > now_row-ret && b > now_col-ret; a--, b--)
{
if (board[a][b] != c)
{
break;
}
}
if ((a == now_row-ret) && (b == now_col-ret))
{
if (board[a][b] == '+')
{
board[a][b] = 'O';
goto exit;
}
else if (board[a+ret+1][b+ret+1] == '+')
{
board[a+ret+1][b+ret+1] = 'O';
goto exit;
}
}
}
i = rand() % row;
j = rand() % row;
if (board[i][j] == '+')
{
board[i][j] = 'O';
goto exit;
//break;
}
}
exit:;
}
char Judge(char board[ROW][COL],int row,int col,int num)
{
int i = 0;
int j = 0;
char ret = 0;
char c = 0;
int a = 0;
int b = 0;
int n = num-1;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
if(board[i][j]!='+')
{
c = board[i][j];
//判断行
if(j<col-n)
{
for(a=i,b=j; b<=j+n; b++)
{
if(board[a][b]!=c)
{
break;
}
}
if((b>j+n))
{
return c;
}
}
//判断列
if(i<row-n)
{
for(a=i,b=j; a<=i+n; a++)
{
if(board[a][b]!=c)
{
break;
}
}
if((a>i+n))
{
return c;
}
}
//判断对角线
//判断右下对角线
if((i<row-n)&&(j<col-n))
{
for(a=i,b=j; (a<=i+n) && (b<=j+n);a++,b++)
{
if(board[a][b]!=c)
{
break;
}
if((a>i+n)&&(b>j+n))
{
return c;
}
}
}
//判断左下对角线
if((i<row-n)&&(j>=n))
{
for(a=i,b=j; (a<=i+n) && (b>=j-n); a++,b--)
{
if(board[a][b]!=c)
{
break;
}
}
if((a>i+n)&&(b<j-n))
{
return c;
}
}
//判断右上对角线
if((i>=n)&&(j<col-n))
{
for(a=i,b=j; (a>=i-n) && (b<=j+n); a--,b++)
{
if(board[a][b]!=c)
{
break;
}
}
if((a<i-n)&&(b>j+n))
{
return c;
}
}
//判断左上对角线
if((i>=n)&&(j>=n))
{
for(a=i,b=j; (a>=i-n) && (b>=j-n); a--,b--)
{
if(board[a][b]!=c)
{
break;
}
}
if((a<i-n)&&(b<j-n))
{
return c;
}
}
}
}
}
//判断是否平局
ret = Isfull(board,ROW,COL);
if(ret=='I')
{
return 'I';
}
return '+';
}
char Isfull(char board[ROW][COL],int row,int col)
{
int i = 0;
int j = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
if(board[i][j]=='+')
{
return '+';
}
}
}
if(i==row && j==col)
{
return 'I';
}
}