三子棋——so easy!

简介: 然后这个test函数里就放一个简易菜单menu()然后再使用do while 这个循环,因为至少要显示一遍如果不想玩才可以关掉。菜单中显示输入1,进入游戏输入0退出游戏。所以我梦需要定义一个变量intput 使用switch(intput)来选择。而注意这个 intput这个变量要放在循环体外面定义。如何在里面定义那么后面while(intput)里面的intput就没有效果。intput的使用范围只在循环体里了。然后你也应该可以看到,这时do while()条件结束也就是intput为0时,这就和上面一致了。好啦基本框架弄好了

文章目录


  • 如何写出三子棋呢,接下来就让我一步一步教你吧!
  • 一、首先要想三子棋怎么玩的?只有知道怎么玩才能知道如何设计呀。
  • 二、那设计又从哪几方面想呢?
  • 1三子棋是多人游戏对吧,要有玩家或者电脑人机的,玩家下棋,电脑跟棋怎样实现呢?.
  • 2.首先需要想象一个三子棋的框架,这个框架可以由一个二维数组arr[][]来搞,那一开始这个框架什么都没有需要对二维数组初始化;然后呢这个是想象的,需要打印出来;
  • 3.打印棋盘后就要思考开始玩家下棋了;注意玩家下棋,下的棋很有讲究,要看这个棋是否合法,在棋盘范围内,下的地04d5c024a9b04379aa11e6955b02c094.png方是否是空的。写代码之前要考虑好这些点。
  • 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);
}


4aa7ef0ec75d4f459ec43fefe5b110f5.png


二、设置一个二维数组,初始化数组为空白。


1.这个二维数组呢,本来应该是3 *3类型。这里可以宏定义两个行与列(为什么呢?)因为如果写3*3了那么这个棋盘就固定了,而如果你想改变这个棋盘大小就可以直接对ROW,COL进行修改,而不用进入函数中对数据进行修改了。


代码如下:这里是放在头文件里的喔。因为要频繁使用所以放在头文件中然后再引用头文件就可以啦~~~引用头文件直接就写#include "game.h"就可以啦。


050d3a6b057244cb99f949d15f49495f.png


#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文件去定义这个函数具体作用啦;


8663e6fb24784657afb008b2f71bb0a7.png


三.接下来就是打印棋盘啦。


de7e3fe12aab4dddbbf972b43bf1eb78.png


请叫我抽象派大师,啊啊啊啊啊啊我尽力了……。。。嘶,,太抽象了,,我能说那个方格是数组吗,两边是空白的。然后再打印一个  |   。下面是三个---和一个|,这个其实是两列哈,我把这个看成一次大循环,然后整体就是三个大循环,而决定这个大循环的是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里定义实现。


5312005295d7427883d6ad97e3cd0358.png

 

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");
  }
}


7ac303e540274433932ce2f2a5130b32.png


打印后就是这样的啦


四.玩家下棋


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函数需要引用头文件。


49eba5622fb74edcb9f579dbb990af7e.png


大家应该懂得一个数%上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;
    }
  }
}


360f14f1233c4515aad75652ea206d58.png


六.判断是谁赢了:    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);声明,然后就是定义了,想一想怎么判断输赢呀,怎样算赢呢,是不是有三个相同的就赢啦,所以有每行有三个相同的,每列有三个相同的,还有对角线相同的情况。下面还是有一定巧妙的,只要是三个*相同就是会返回*然后就是玩家赢了,而如果是三个#相同则就会返回#则是电脑赢了。


9ec5d2cc4a7940e3ac6efdde4ee8e3f8.png


还有一个平局怎么判断呢?这个就简单啦,再写一个函数如果棋盘满了就返回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表示继续比赛。


最后:到现在基本写完了,看看成品吧。


e47fd758ac3944e28a6c5f5c1de28edc.png


总结:如何写三子棋——思路:


1.初始化数组


2.打印棋盘


3.玩家下棋


4.电脑下棋


5.判断输赢


如果想要看代码的可以去我的github里看      :  https://github.com/ITwei6   代码在12.3里。感谢大家的观看!谢谢!d3e666e8de0649d7a4c38def4d64908c.pngd3e666e8de0649d7a4c38def4d64908c.png


64756491d4ec4051b4c0f162192ff488.png

相关文章
|
6月前
|
C语言
简易三子棋的实现
简易三子棋的实现
|
5月前
小游戏:三子棋的代码实现
小游戏:三子棋的代码实现
33 3
三子棋的创建
三子棋的创建
78 0
|
6月前
|
人工智能 C语言
三子棋小游戏
三子棋小游戏
|
6月前
|
算法 C语言
三子棋小游戏(可改棋盘大小)
三子棋小游戏(可改棋盘大小)
73 0
|
11月前
简单三子棋的实现
简单三子棋的实现
62 0
|
程序员 C语言
三子棋(超详细)
三子棋(超详细)
|
算法 编译器 C语言
傻瓜式的三子棋
傻瓜式的三子棋
|
C语言
C/【三子棋】
C/【三子棋】
三子棋的实现有这么简单吗?
三子棋的实现有这么简单吗?
50 0