三子棋游戏规则:
游戏是在一个3*3的棋盘里面下棋的。
只要有三个一样的连成一条线,就表示有一方胜出;如果下完了9个格子还没有玩家胜出,游戏为平局;
实现思路:
1.初始化棋盘数组
2.绘制棋盘
3.玩家下棋
4.电脑下棋
5.判断输赢
首先创建头文件
//ThreeChess.h
#ifndef __GAME_H__
#define __GAME_H__
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(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);
#endif //__GAME_H__
逐个分析:
1.使用字符型二维数组表示棋盘,棋盘上有三种状态,字符0表示初始化状态
创建源文件
//ThreeChess.c
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] = '0';
}
}
}
2.玩家下棋:字符1位玩家状态,玩家棋子键盘输入坐标,判断输入坐标是否有棋子,或者是否越界
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x, y;
while (1)
{
printf("请输入坐标:\n");
scanf("%d%d", &y, &x);
if (board[x - 1][y - 1] == '0')
{
board[x - 1][y - 1] = '1';
break;
}
printf("输入坐标不合法\n");
}
}
3.电脑下棋:字符‘*’表示电脑的棋子,电脑下棋也会有一些判断,先判断自己是否有2个子,再判断玩家是否有2个子。如果2中情况都没有出现,电脑就随机落子,当然也要判断落子位置是否合法
//
void Computermove(char board[ROW][COL], int row, int col)
{
int Computer_x = 0;
int Computer_y = 0;
if (ComputerHas2(board, row, col) == 1)
{
return;
}
if (playerHas2(board, row, col) == 1)
{
return;
}
while (1)
{
Computer_x = rand() % row;
Computer_y = rand() % col;
if (board[Computer_x][Computer_y] == '0')
{
board[Computer_x][Computer_y] = '*';
break;
}
}
//判断电脑是否有2个子的函数
int ComputerHas2(char board[ROW][COL], int row, int col)
{
int i, j;
int flag = 0;
//判断玩家是否横着有2个
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[i][j] == '*')
{
flag++;
}
}
//表示检测到有两个
if (flag == 2)
{
flag = 0;
if (board[i][0] == '0')
{
board[i][0] = '*';
return 1;
}
else if (board[i][1] == '0')
{
board[i][1] = '*';
return 1;
}
else if (board[i][2] == '0')
{
board[i][2] = '*';
return 1;
}
}
flag = 0;
}
flag = 0;
//判断两个竖行
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[j][i] == '*')
{
flag++;
}
}
//表示检测到有两个竖行
if (flag == 2)
{
flag = 0;
if (board[0][i] == '0')
{
board[0][i] = '*';
return 1;
}
else if (board[1][i] == '0')
{
board[1][i] = '*';
return 1;
}
else if (board[2][i] == '0')
{
board[2][i] = '*';
return 1;
}
}
flag = 0;
}
flag = 0;
//判断玩家是否有两个斜着的1///
for (i = 0; i < row; i++)
{
if (board[i][i] == '*')
{
flag++;
}
}
if (flag == 2)
{
flag = 0;
if (board[0][0] == '0')
{
board[0][0] = '*';
return 1;
}
else if (board[1][1] == '0')
{
board[1][1] = '*';
return 1;
}
else if (board[2][2] == '0')
{
board[2][2] = '*';
return 1;
}
}
flag = 0;
//判断玩家是否有两个斜着的1//
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == '*' && (i + j == 2))
{
flag++;
}
}
}
if (flag == 2)
{
flag = 0;
if (board[0][2] == '0')
{
board[0][2] = '*';
return 1;
}
else if (board[1][1] == '0')
{
board[1][1] = '*';
return 1;
}
else if (board[2][0] == '0')
{
board[2][0] = '*';
return 1;
}
}
flag = 0;
return 0;
}
//判断玩家是否有两个连子的函数
//判断玩家是否有两个连着的
int playerHas2(char board[ROW][COL], int row, int col)
{
int i, j;
int flag = 0;
//判断玩家是否横着有2个
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[i][j] == '1')
{
flag++;
}
}
//表示检测到有两个
if (flag == 2)
{
flag = 0;
if (board[i][0] == '0')
{
board[i][0] = '*';
return 1;
}
else if (board[i][1] == '0')
{
board[i][1] = '*';
return 1;
}
else if (board[i][2] == '0')
{
board[i][2] = '*';
return 1;
}
}
flag = 0;
}
flag = 0;
//判断两个竖行
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[j][i] == '1')
{
flag++;
}
}
//表示检测到有两个竖行
if (flag == 2)
{
flag = 0;
if (board[0][i] == '0')
{
board[0][i] = '*';
return 1;
}
else if (board[1][i] == '0')
{
board[1][i] = '*';
return 1;
}
else if (board[2][i] == '0')
{
board[2][i] = '*';
return 1;
}
}
flag = 0;
}
//判断玩家是否有两个斜着的1///
for (i = 0; i < row; i++)
{
if (board[i][i] == '1')
{
flag++;
}
}
if (flag == 2)
{
flag = 0;
if (board[0][0] == '0')
{
board[0][0] = '*';
return 1;
}
else if (board[1][1] == '0')
{
board[1][1] = '*';
return 1;
}
else if (board[2][2] == '0')
{
board[2][2] = '*';
return 1;
}
}
flag = 0;
//判断玩家是否有两个斜着的1//
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == '1' && i + j == 2)
{
flag++;
}
}
}
if (flag == 2)
{
flag = 0;
if (board[0][2] == '0')
{
board[0][2] = '*';
return 1;
}
else if (board[1][1] == '0')
{
board[1][1] = '*';
return 1;
}
else if (board[2][0] == '0')
{
board[2][0] = '*';
return 1;
}
}
flag = 0;
return 0;
}
4. 判断游戏是否胜利:当任意一方下到第三个棋子时就会开始调用这个函数
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int Computer_winFlag = 0;
int Player_winFlag = 0;
///
//判断电脑是否胜利/
///
//判断电脑三个横着的
Computer_winFlag = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[i][j] == '*')
{
Computer_winFlag++;
}
}
if (Computer_winFlag == 3)
{
printf("情况1\n");
return '*';
}
Computer_winFlag = 0;
}
//判断电脑三个竖着的
Computer_winFlag = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[j][i] == '*')
{
Computer_winFlag++;
}
}
if (Computer_winFlag == 3)
{
printf("情况2\n");
return '*';
}
Computer_winFlag = 0;
}
Computer_winFlag = 0;
//电脑三个斜着的1
if ((board[0][0] == '*') && (board[1][1] == '*') && (board[2][2] == '*'))
{
printf("情况3\n");
return '*';
}
//电脑三个斜着的2
if ((board[0][2] == '*') && (board[1][1] == '*') && (board[2][0] == '*'))
{
printf("情况4\n");
return '*';
}
///
//判断玩家是否胜利/
///
//判断玩家三个横着的
Player_winFlag = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[i][j] == '1')
{
Player_winFlag++;
}
}
if (Player_winFlag == 3)
{
return '1';
}
Player_winFlag = 0;
}
Player_winFlag = 0;
//判断玩家三个竖着的
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (board[j][i] == '1')
{
Player_winFlag++;
}
}
if (Player_winFlag == 3)
{
return '1';
}
Player_winFlag = 0;
}
Player_winFlag = 0;
//玩家三个斜着的1
if ((board[0][0] == '1') && (board[1][1] == '1') && (board[2][2] == '1'))
{
return '1';
}
//玩家三个斜着的2
if ((board[0][2] == '1') && (board[1][1] == '1') && (board[2][0] == '1'))
{
return '1';
}
return '0';
}
//主函数
int main()
{
srand((unsigned int)time(NULL));
char board[ROW][COL];
int stepCount = 0;//记录下棋步数,用来判断是否平局
int option = 0;
while (1)
{
option = showMenu();
switch (option)
{
case 0: return 0;
case 1: {
InitBoard(board, ROW, COL);
stepCount = 0;
while (1)
{
DisplayBoard(board, ROW, COL);
PlayerMove(board, ROW, COL);
++stepCount;
if (stepCount == ROW*COL)
{
printf("平局!\n");
DisplayBoard(board, ROW, COL);
break;
}
if (stepCount > 4)//从第5步开始判断游戏是否有人胜利
{
if (IsWin(board, ROW, COL) == '1')
{
printf("玩家胜利! \n");
DisplayBoard(board, ROW, COL);
break;
}
}
Computermove(board, ROW, COL);
++stepCount;
if (stepCount > 4)//从第5步开始判断游戏是否有人胜利
{
if (IsWin(board, ROW, COL) == '*')
{
printf("电脑胜利! \n");
DisplayBoard(board, ROW, COL);
break;
}
}
}
}break;
default: printf("选择错误!\n");
break;
}
}
return 0;
}
ThreeChess.c中的头文件包含
#include"ThreeChess.h"
#include "menu.h"
ThreeChess.h中已在第一行给出
//menu.h头文件
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
int showMenu()
{
int option;
printf("*******************************\n");
printf("****1.开始游戏 0.退出游戏****\n");
printf("*******************************\n");
printf("请输入您的选择>");
scanf("%d", &option);
return option;
}
程序运行截图:
总结:函数返回值必须考虑所有情况,必须让这个函数有一个自定义的返回值。
当我写IsWin函数时,判断玩家胜利会返回字符 ' 1 ',判断电脑胜利会返回 ' * ',但是没考虑这两个都没有的情况,程序运行起来之后,发现没走几步,电脑没有3子连着的情况,但是显示电脑胜利,大半天没搞清楚为什么,然后我在每个电脑可能赢的情况处都下了断点,当显示电脑胜利之后程序并没有进入任何一个断点,但是函数返回了' * ',这下我才意识到函数随机返回了一个值,然后这个值正好是' * '是这个字符。