此代码可以根据你所规定行数,来进行游戏,不仅限于3行3列的
设计思路
- 由于这个代码相较于平常所写的,代码比较多,故我采用多文件管理,减少维护成本
- 函数声明放在game.h头文件
- 与游戏有关函数定义放在game.c源文件
- main函数单独放在main.c中
- 设计代码时,先写出主体逻辑,然后边测试逻辑的正确性边进行代码的具体实现
如下:
先从主函数开始写出大体逻辑
int main(void)
{
int input = 0;
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!");
break;
default:
printf("输入错误,请重新输入!");
break;
}
} while (input);
return 0;
}
菜单函数
void menu()
{
printf("**********************************\n");
printf("***** 1.play 0.exit *****\n");
printf("**********************************\n");
}
写出game函数的逻辑
1. **你要下棋要棋盘,所以创建一个二维数组来充当棋盘** 1. **此时就要有初始化棋盘的函数,先写出来** 1. **打印棋盘出来让玩家下棋,所以需要一个打印棋盘的函数** 1. **此时玩家就可以开始下棋了,需要一个玩家下棋的函数** 1. **打印棋盘** 1. **玩家下完棋后,电脑下棋,需要一个电脑下棋的函数** 1. **并且在玩家或者电脑下完棋后,需要判断1.谁赢了 2. 是否平局(棋盘是否已满)若上述都没有发生则继续 ,故这是一个玩家下棋,电脑下棋是一个循环的过程**
void game()
{
char board[ROW][COL];
char ret = 0;
srand((unsigned)time(NULL));
InitBoard(board, ROW, COL);
PrintBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, 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++)
{
printf(" %c | %c | %c | %c | %c \n", board[i][0],board[i][1],.. board[i][4]);
if(i<row-1)
printf("---|---|---|---|---\n");
}
}
但是上述代码有个问题,就是它的列数是固定的,所以我们又要在行的规律基础上找出列的规律,从而写出代码
我们观察可以发现,棋盘的每一列都是由两部分组成:只是棋盘的最后一列的第二部分没有打印而已
- 第一部分:三个空格
- 第二部分:一个 |
- 对于分割部分类似
代码如下:
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//棋盘行的第一部分 | |
int j = 0;
for (j = 0; j < col; j++)
{
//棋盘列的第一部分
printf(" %c ", board[i][j]);
//棋盘列的第二部分
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
//棋盘行的第二部分---|---|---
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
//棋盘列的第一部分
printf("---");
//棋盘列的第二部分
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
玩家走
逻辑比较简单,就是判断是否覆盖以及是否越界,注意:玩家的坐标和程序员的坐标不一样
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家走:");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置已被占!");
}
}
else
{
printf("请重新输入!");
}
}
}
电脑走
电脑走只需考虑覆盖问题即可
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑走:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断棋盘情况
分为四种情况:
- 玩家赢 返回‘*’
- 电脑赢,返回‘#
判断谁赢分为四种情况考虑:直接返回相同的那个字符,若返回*则玩家赢,返回#则电脑赢
- 行相同:
- 列相同:
- 主对角线相同:
- 副对角线相同:
- 平局(棋盘是否已满),返回 ’Q‘
- 继续游戏,返回-‘C’
完善game函数逻辑
void game()
{
char board[ROW][COL];
char ret = 0;
srand((unsigned)time(NULL));
InitBoard(board, ROW, COL);
PrintBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if ('C' != ret)
break;
ComputerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if ('C' != ret)
break;
}
if ('#' == ret)
printf("电脑赢!\n");
if ('*' == ret)
printf("玩家赢!\n");
if ('Q' == ret)
printf("平局!\n");
}
判断棋盘情况的函数
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
char flag[ROW]; //保存数据来判断是否相同
int temp = 0;
//判断行相同
for (i = 0; i < row; i++)
{
//将每一行的字符传给flag数组
for (j = 0; j < col; j++)
{
flag[j] = board[i][j];
}
//判断flag数组中是否都相同
for (j = 0; j < col - 1; j++)
{
if (flag[j] != flag[j + 1])
{
break;
}
}
if (col-1 == j && flag[0] != ' ') //若跳出来时j=col-1,则说明比较完毕,都相同
{
return flag[0];
}
}
//判断列相同
while (temp < col)
{
//将每一类分别传给flag数组
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++) //对于列是否赢
{
if (temp == j)
{
flag[i] = board[i][j];
break;
}
}
}
//判断flag中是否相同
for (j = 0; j < col - 1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
temp++;
}
//判断主对角线相同
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (i == j)
{
flag[i] = board[i][j];
}
}
}
for (j = 0; j < col-1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
//判断副对角线相同,因为两个坐标加起来恰好等于列数(行数)-1,所以可以设置如下
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (i + j == (col - 1))
{
flag[i] = board[i][j];
}
}
}
for (j = 0; j < col - 1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
//是否平局,将判断棋盘是否已满封装为一个函数
int ret = IsFull(board, row, col);
if (1 == ret)
return 'Q';
return 'C';
}
判断棋盘是否已满
int 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 0;
}
}
return 1;
}
完整代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 5
#define COL 5
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col);
//玩家走
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑走
void ComputerMove(char board[ROW][COL], int row, int col);
//判断棋盘情况
char IsWin(char board[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
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;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家走:");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置已被占!");
}
}
else
{
printf("请重新输入!");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑走:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
char flag[ROW];
int temp = 0;
//判断行
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
flag[j] = board[i][j];
}
for (j = 0; j < col; j++)
{
if (j == col - 1)
break;
if (flag[j] != flag[j + 1])
{
break;
}
}
if (col-1 == j && flag[0] != ' ')
{
return flag[0];
}
}
//判断列
while (temp < col)
{
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++) //对于列是否赢
{
if (temp == j)
{
flag[i] = board[i][j];
break;
}
}
}
for (j = 0; j < col - 1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
temp++;
}
//主对角线
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (i == j)
{
flag[i] = board[i][j];
}
}
}
for (j = 0; j < col-1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
//副对角线
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (i + j == (col - 1))
{
flag[i] = board[i][j];
}
}
}
for (j = 0; j < col - 1; j++)
{
if (flag[j] != flag[j + 1])
break;
}
if (j == col - 1 && flag[0] != ' ')
return flag[0];
//是否平局
int ret = IsFull(board, row, col);
if (1 == ret)
return 'Q';
return 'C';
}
//判断棋盘是否已满
int 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 0;
}
}
return 1;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("**********************************\n");
printf("***** 1.play 0.exit *****\n");
printf("**********************************\n");
}
void game()
{
char board[ROW][COL];
char ret = 0;
srand((unsigned)time(NULL));
InitBoard(board, ROW, COL);
PrintBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if ('C' != ret)
break;
ComputerMove(board, ROW, COL);
PrintBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if ('C' != ret)
break;
}
if ('#' == ret)
printf("电脑赢!\n");
if ('*' == ret)
printf("玩家赢!\n");
if ('Q' == ret)
printf("平局!\n");
}
int main(void)
{
int input = 0;
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!");
break;
default:
printf("输入错误,请重新输入!");
break;
}
} while (input);
return 0;
}