局部最终效果
3*3
6*6
(由于不会屏幕录制,就截了一小部分图
下面按照编程步骤给出此游戏实现过程
(分三个源文件,两个.cpp一个.h,一个cpp用于测试游戏,一个cpp用于函数实现,一个.h用于函数声明以及符号定义及头文件声明)
游戏初始部分,进入游戏之前的部分
void menu()
{
printf("*********************\n");
printf("**** 1. game *****\n");
printf("**** 0. exit *****\n");
printf("*********************\n");
}
void test()
{
srand((unsigned int)time(NULL));
int ret = 0;
do
{
menu();
printf("请输入你的选项:\n");
scanf("%d", &ret);
switch (ret)
{
case 1:
game();
break;
case 0:
printf("退出成功\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (ret);
}
int main()
{
test();
return 0;
}
注意此do-while结构的使用以及switch语句
game()函数的实现(三子棋游戏的过程)
#include"三子棋.h"
void game()
{
char ret;
char chess[ROW][COL];
Init_chess(chess, ROW, COL); //初始化棋盘,使棋盘全都为空格
Print_chess(chess, ROW, COL); //打印棋盘
while (1)
{
Gamer_move(chess, ROW, COL); //玩家移动
Print_chess(chess, ROW, COL);
ret = Is_win(chess, ROW, COL); //判断输赢
if (ret != 'C')
break;
Computer_move(chess, ROW, COL); //电脑移动
Print_chess(chess, ROW, COL);
ret = Is_win(chess, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '#')
printf("游戏结束,玩家赢\n");
else if (ret == '*')
printf("游戏结束,电脑赢\n");
else if (ret == 'P')
printf("游戏结束,平局\n");
}
这是游戏过程的实现,包括初始化棋盘,打印棋盘,玩家移动,电脑移动,判断输赢...
里面的每个功能都封装成函数,使程序模块化
三子棋.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define ROW 3
#define COL 3
// 初始化棋盘
void Init_chess(char arr[ROW][COL], int row, int col);
// 打印棋盘
void Print_chess(char arr[ROW][COL], int row, int col);
// 玩家下棋
void Gamer_move(char arr[ROW][COL], int row, int col);
// 判断输赢
char Is_win(char arr[ROW][COL], int row, int col);
// 电脑下棋
void Computer_move(char arr[ROW][COL], int row, int col);
注意里面的ROW,COL的定义,目的是使这个棋盘的大小不固定,而是由ROW,COL指定,以实现一改全改,这样棋盘的大小可以随意指定,否则若以后想改变棋盘大小,就会出现很多地方的数字需要更改,很麻烦。
Init_chess()
void Init_chess(char chess[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
chess[i][j] = ' ';
}
}
}
print_chess()
void Print_chess(char chess[ROW][COL], int row, int col)
{
// row 行 col 列
for (int i = 0; i < row; i++)
{
// 每一次循环 打印一组
// 先打印 | |
for (int j = 0; j < col; j++)
{
printf(" %c ", chess[i][j]);
if (j != col - 1)
printf("|");
}
printf("\n");
//再打印---|---|---
if (i != row-1)
for (int j = 0; j < col; j++)
{
printf("---");
if (j != col - 1)
printf("|");
}
printf("\n");
}
}
注意里面打印时用的是row,col这样的变量,不是3这样的常量
Gamer_move() 以及 Computer_move()
void Gamer_move(char chess[ROW][COL], int row, int col)
{
while (1)
{
printf("请输入你选择的坐标\n");
int x = 0, y = 0;
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (chess[x - 1][y - 1] == ' ')
{
chess[x - 1][y - 1] = '#';
break;
}
else
printf("该位置已被占用,请重新选择\n");
}
else
{
printf("输入错误,请重新输入\n");
}
}
}
void Computer_move(char chess[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
while (1)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (chess[x-1][y-1] == ' ')
{
chess[x-1][y-1] = '*';
break;
}
}
}
Is-win() 旧版
char Is_win(char chess[ROW][COL], int row, int col)
{
//人# 机器* 平局P 继续 C
// 先判断是否有人赢 横三行
for (int i = 0; i < 3; i++)
{
if (chess[i][0] == chess[i][1] && chess[i][1] == chess[i][2] && chess[i][1] != ' ')
return chess[i][1];
}
if (chess[0][0] == chess[1][1] && chess[1][1] == chess[2][2] && chess[1][1] != ' ')
return chess[1][1];
if (chess[2][0] == chess[1][1] && chess[0][2] == chess[1][1] && chess[1][1] != ' ')
return chess[1][1];
for (int i = 0; i < 3; i++)
{
if (chess[0][i] == chess[1][i] && chess[1][i] == chess[2][i] && chess[1][i] != ' ')
return chess[1][i];
}
char c = Is_continue(chess, row, col);
return c;
}
上方Is_win() 不够好,这个函数只限于3*3棋盘的判断,如果是其他的就不适用了,所以下方给出了升级版
Is_win() 新版
char Is_win(char chess[ROW][COL], int row, int col)
{
//人# 机器* 平局P 继续 C
// 先判断是否有人赢 横
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col - 2; j++)
{
if (chess[i][j] == chess[i][j + 1] && chess[i][j + 1] == chess[i][j + 2] && chess[i][j + 1] != ' ')
return chess[i][j + 1];
}
}
//竖
for (int i = 0; i < col; i++)
{
for (int j = 0; j < row - 2; j++)
{
if (chess[j][i] == chess[j + 1][i] && chess[j + 1][i] == chess[j + 2][i] && chess[j + 1][i] != ' ')
return chess[j + 1][i];
}
}
//右下
for (int i = 0; i < row - 2; i++)
{
for (int j = 0; j < col - 2; j++)
{
if (chess[i][j] == chess[i + 1][j + 1] && chess[i + 1][j + 1] == chess[i + 2][j + 2] && chess[i + 1][j + 1] != ' ')
return chess[i][j];
}
}
//左下
for (int i = row - 1; i >= 2; i--)
{
for (int j = col - 1; j >= 2; j--)
{
if (chess[i][j] == chess[i + 1][j - 1] && chess[i + 1][j - 1] == chess[i + 2][j - 2] && chess[i][j] != ' ')
return chess[i][j];
}
}
char c = Is_continue(chess, row, col);
return c;
}
此函数适用于所有row与col,
解析:
如图所示,如果是6*6的棋盘,若想判断输赢,也是横三个,竖三个,斜着三个
这样的话,判断时就必须有限制条件了,因为如果是对于1 5这个坐标,往右判断三个就会出现数组越界的情况,所以。
只有红线所及的区域,可以进行向下或者向右的判断,也就是6*6的棋盘,只有4*4的区域可以进行延申判断。
这个是斜着的,6*6的棋盘,左上4*4进行右下方判断,右上4*4进行左下方判断。这样,也就有了上方的新版Is_win()
Is_continue() (辅助Is_win函数的实现)
char Is_continue(char chess[ROW][COL], int row, int col)
{
int flag = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (chess[i][j] == ' ')
flag = 1; //有一个是空格,所以表示没满继续
}
}
if (flag)
return 'C';
else
return 'P';
}
------------------------------------------------------------