文章目录
- 如何写出三子棋呢,接下来就让我一步一步教你吧!
- 一、首先要想三子棋怎么玩的?只有知道怎么玩才能知道如何设计呀。
- 二、那设计又从哪几方面想呢?
- 1三子棋是多人游戏对吧,要有玩家或者电脑人机的,玩家下棋,电脑跟棋怎样实现呢?.
- 2.首先需要想象一个三子棋的框架,这个框架可以由一个二维数组arr[][]来搞,那一开始这个框架什么都没有需要对二维数组初始化;然后呢这个是想象的,需要打印出来;
- 3.打印棋盘后就要思考开始玩家下棋了;注意玩家下棋,下的棋很有讲究,要看这个棋是否合法,在棋盘范围内,下的地方是否是空的。写代码之前要考虑好这些点。
- 4.玩家下棋后那电脑跟棋,电脑下棋也是有要求的,需要和玩家下棋的条件一样,下棋是否合法,越界没,有空地方可以下吗?有棋的地方肯定不能下了呀。
- 5.这时玩家和电脑都可以正常下棋了,下面要想什么呢?下棋就要看谁嬴谁输了呀,每下一步棋都有可能有一方赢或输,所以在每次玩家或电脑下棋之后要进行判断是否有输赢。
总体就是从以下几个方面思考
- 设置一个二维数组,初始化数组(为空白)
- 打印棋盘
- 玩家下棋
- 电脑下棋
- 判断输赢
前言
提示:这里可以添加本文要记录的大概内容:以上都是我在写代码之前的思路喔,接下来我会用代码来解释其中许多细节部分。还有这里要分装各个函数,这样比较方便使用,我会建立一个test.c文件用来测试游戏,建立一个game.c用来实现定义游戏各函数的功能。然后建立一个game.h头文件用来声明各函数。(函数声明一般都放在头文件中)
一、先弄出一个三子棋基本界面,,嗯,,比较简陋。
int main() { test();// test()进行测试; return 0; }
然后这个test函数里就放一个简易菜单menu()然后再使用do while 这个循环,因为至少要显示一遍如果不想玩才可以关掉。菜单中显示输入1,进入游戏输入0退出游戏。所以我梦需要定义一个变量intput 使用switch(intput)来选择。而注意这个 intput这个变量要放在循环体外面定义。如何在里面定义那么后面while(intput)里面的intput就没有效果。intput的使用范围只在循环体里了。然后你也应该可以看到,这时do while()条件结束也就是intput为0时,这就和上面一致了。好啦基本框架弄好了
void meun() { printf("************************\n"); printf("****** 1.play ******\n"); printf("****** 0.exit ******\n"); printf("************************\n"); }
void test() { int intput; do { meun(); printf("请输入:"); scanf("%d", &intput); switch(intput) { case 1: game();//这里输入 1进入游戏 break; case 0: printf("退出游戏\n"); break; default: printf("输入错误\n"); break; } } while (intput); }
二、设置一个二维数组,初始化数组为空白。
1.这个二维数组呢,本来应该是3 *3类型。这里可以宏定义两个行与列(为什么呢?)因为如果写3*3了那么这个棋盘就固定了,而如果你想改变这个棋盘大小就可以直接对ROW,COL进行修改,而不用进入函数中对数据进行修改了。
代码如下:这里是放在头文件里的喔。因为要频繁使用所以放在头文件中然后再引用头文件就可以啦~~~引用头文件直接就写#include "game.h"就可以啦。
#pragma once #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3//3行 #define COL 3//3列
2.(在test.c文件里开始完善game()函数)设置字符数组char board[ROW] [COL];自定义一个函数作用是初始化它 Init_board(board, ROW, COL);然后在头文件里声明。void Init_board(char board[ROW][COL], int row,int col);// 初始化函数声明。声明后就要去game.c文件去定义这个函数具体作用啦;
三.接下来就是打印棋盘啦。
请叫我抽象派大师,啊啊啊啊啊啊我尽力了……。。。嘶,,太抽象了,,我能说那个方格是数组吗,两边是空白的。然后再打印一个 | 。下面是三个---和一个|,这个其实是两列哈,我把这个看成一次大循环,然后整体就是三个大循环,而决定这个大循环的是ROW行决定的,所以呢,我们定义一个i;
弄一个for (i = 0;i < row;i++)里面呢 就是循环每行(大循环)打印的了,,里面要写的代码是每列是打印什么了,可以设置一个变量j int j;
for (j = 0;j < col;j++) 循环 ,看! 先是空格 数组 空格 然后换行重新打印 | (为什么呢?)注意最后一列是没有 |的这说明 | 可不是循坏 col(3) 次喔,最后一次不打印 |所以这里要写一个条件了 if (j < col - 1) 才可以打印 |。这个循环结束,要手动换行。换行后就要打印---打印三个-然后再打印 | 了 ,这个在列的循环中没什么问题,但问题出现在行的打印中,,注意最后一行的最后是没有打印的。所以这里又要设置条件了,这个- - - |打印的条件应该是if(iPrint_board(board, ROW, COL);//打印棋盘,在头文件里声明void Print_board(char board[ROW][COL], int row, int col);,在game.c里定义实现。
void Print_board(char board[ROW][COL], int row, int col) { int i; for (i = 0;i < row;i++) { int j; for (j = 0;j < col;j++) { printf(" %c ",board[i][j]); if (j < col - 1) { printf("|"); } } printf("\n"); if (i < row - 1) { for (j = 0;j < col;j++) { printf("---"); if (j < col - 1) { printf("|"); } } } printf("\n"); } }
打印后就是这样的啦
四.玩家下棋
test.c里设置函数Player_move(board, ROW, COL);//玩家开始下棋;头文件声明void Player_move(char board[ROW][COL], int row, int col);game.c里实现函数功能 。这里要注意玩家下棋,要注意一般玩家玩这种有下标的游戏,,是从1开始数的而不是像我们程序员从下标为0开始数的所以呢,当玩家要输入的值应该是要在代码上是大的哈,程序上写要减一喔,int x = 0; int y = 0; scanf("%d%d", &x, &y);玩家输入两个值,这两个值要合法,不能越界。if (x >= 1 && x <= row && y >= 1 && y <= col)这时是合法的。合法后还要判断下的地方是否有空,如果没空就再找所以这个过程是个循环,然后循坏结束就是如果有空就让board[][]==*并且break跳出循环;
void Player_move(char board[ROW][COL], int row, int col)//玩家先开始下棋; { printf("玩家下棋\n"); while (1) { //首先要判断下棋是否合法;范围在哪? printf("请输入要下棋的坐标:"); int x = 0; int y = 0; scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //还要判断下棋的地方有没有地方可以下。 if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已被占用请重新输入\n"); } } else { printf("坐标非法\n"); } }
五. 电脑下棋。
电脑下棋呢,这个就要涉及一个生成随机值的知识点了,,这个我会过几天写个猜数字游戏里面会介绍到。这里就直接写告诉你们怎么使用了,并不详细介绍哈。
rand()函数就是用来生成随机数的函数,调用这个函数之前必须要调用srand()函数,srand()函数里面放一个会变化的数就能使rand()函数生成随机数,而什么是不断变化的呢? 对!就是时间,这里又要使用time(NULL)函数来产生时间戳。这里面没有什么可以要给time()放的就放一个空指针进去。调用rand()函数需要引用头文件,time函数需要引用头文件。
大家应该懂得一个数%上n, 得到的数范围就是0~n-1,不懂的现在懂啦,
/
int x, y; x = rand() % row;//x只能是0 1 2 y = rand() % col;//y也只能是0 1 2;
这时x,y的值就已经合法了,接下来就考虑电脑下的棋是否有空,跟玩家那个是一样的。只不过电脑下棋是#
void Computer_move(char board[ROW][COL], int row, int col)//电脑下棋,也要判断合法性; { printf("电脑下棋\n"); while (1) { int x, y; x = rand() % row;//x只能是0 1 2 y = rand() % col;//y也只能是0 1 2; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
六.判断是谁赢了: char is_win(char board[ROW][COL], int row, int col);
玩家走一步,可能会赢,电脑走一步也可能会赢,也可能是平局,也可能是谁都没赢也没平局,继续走。这里要想到,玩家走电脑走玩家走电脑走,这个过程是个循环,而跳出这个循环的条件就是有一方赢了或输了或平局,那就break;跳出循环。这里先如果函数返回 * 则表明玩家赢,返回#则表示电脑赢,返回Q则表示平局。而返回C则表示继续。最上面就已经说过玩家走一次就要判断一次,电脑走一次也要判断一次。所以一旦出现不是C了情况了那就直接break;跳出循环。然后再讨论ret到底是什么。
while (1) { Player_move(board, ROW, COL);//玩家开始下棋; Print_board(board, ROW, COL);//每下完棋都有可能会英所以需要判断一下 //判断输赢; ret =is_win(board, ROW, COL); if (ret != 'C') { break; } Computer_move(board, ROW, COL);//电脑开始下棋; Print_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') { break; } }
接下来就是讨论ret到底是谁了
if (ret == '#') { printf("电脑赢了\n"); } else if (ret == '*') printf("玩家赢了\n"); else if (ret == 'Q') printf("平局\n");
好啦到这里,test.c基本完成还有最后一个函数(判断输赢)没有声明和定义。char is_win(char board[ROW][COL], int row, int col);声明,然后就是定义了,想一想怎么判断输赢呀,怎样算赢呢,是不是有三个相同的就赢啦,所以有每行有三个相同的,每列有三个相同的,还有对角线相同的情况。下面还是有一定巧妙的,只要是三个*相同就是会返回*然后就是玩家赢了,而如果是三个#相同则就会返回#则是电脑赢了。
还有一个平局怎么判断呢?这个就简单啦,再写一个函数如果棋盘满了就返回1,否则就返回0;
int is_full(char board[ROW][COL], int row, int col) { int i, j; for (i = 0;i < row;i++) { for (j = 0;j < col;j++) { if (board[i][j] == ' ') return 0; } } return 1; }
如果返回1了那表面这个函数平局那就is_win函数就返回Q就行了
if (is_full(board, ROW, COL) == 1) { return 'Q'; }
最后如果这些都没有发生那么 char is_win(char board[ROW][COL], int cow, int col)这个函数就自动返回C表示继续比赛。
最后:到现在基本写完了,看看成品吧。
总结:如何写三子棋——思路:
1.初始化数组
2.打印棋盘
3.玩家下棋
4.电脑下棋
5.判断输赢
如果想要看代码的可以去我的github里看 : https://github.com/ITwei6 代码在12.3里。感谢大家的观看!谢谢!