【C语言从0到1之《三子棋》的实现】

简介: 新手小白想学好编程,一定要注重代码实现。所以今天我将带领大家写一个小游戏《三子棋》。需要具备的知识有循环·数组·函数是不是都学过了呢?那么我们来动手实操检验一下成果~~~

前言


新手小白想学好编程,一定要注重代码实现。


所以今天我将带领大家写一个小游戏《三子棋》。


需要具备的知识有循环·数组·函数


是不是都学过了呢?


那么我们来动手实操检验一下成果~~~


思路


首先我们要有个菜单,选择开始或者退出


我们要有个井字格来划分区域


我们要能下棋


电脑要和我们对局


要判断是否胜利


具体实现

菜单

void memu() {
    printf("********************************\n");
    printf("************* 1->开始 **********\n");
    printf("************* 0->退出 **********\n");
    printf("********************************\n");
    printf("->");
}

这里我们用到printf打印一个界面


接下来就要输入1或者0来选择


是不是非常简单,我们接着往下看~


主函数


一个switch语句进行选择


int main() {
    memu();
    srand((unsigned int)time(NULL));//电脑随机下棋,后续会有解释
    int input;
    scanf("%d", &input);
    switch(input) {
    case 0:
        exit(0);//强制退出程序
        break;
    case 1:
        game();//后续接着进入游戏
        break;
    default:
        printf("输入错误!");
        break;
    }
}


初始化数组


我们要使用一个char型数组来存储棋子


先将数组初始化


void Init(char board[ROW][COL], int row, int col) {
    for (int i=0; i < row; i++) {
        for (int j=0; j < col; j++) {
            board[i][j] = ' ';
        }
    }
}


打印界面


我们定义一个函数专门打印界面


打印用数组存储下的棋


以及分割的符号


我们定义row为行,col为列


void print(char board[ROW][COL], int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf(" %c ", board[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");
        }
    }
}


接下来我们就要开始下棋了


tip:玩家为* 电脑为#


玩家先手


这里我们要考虑几个问题:


输入的坐标并不是数组的下标


输入坐标超过数组的界限怎么办

void player_move(char board[ROW][COL], int row, int col) {
    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");
        }
    }
}


判断棋盘是否满了

在对局中我们每次下棋都要判断棋盘是否满了


如果已经满了还未分出胜负,则为平局

void is_full(char board[ROW][COL], int row, int col) {
    int flag = 0;
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            if (board[i][j] == ' ') {
                flag++;
            }
        }
    }
    if (flag == 0) {
        printf("平局\n");
        exit(0);
    }
}



电脑对局

在这里我们用随机数的方式实现电脑下棋


void computer_move(char board[ROW][COL], int row, int col) {
    printf("AI下棋:\n");
    while (1) {
        is_full(board, ROW, COL);
        int x = rand() % row;
        int y = rand() % col;
        //使用rand()函数
        //之前我们使用srand((unsigned int)time(NULL))
        //就是以时间来求随机数以求更随机
        if (board[x][y] == ' ') {
            board[x][y] = '#';
            break;
        }
    }
}


判断胜负


三子棋的规则是什么?


三个相同的棋在同行同列或者对角线上即为胜利


char is_win(char board[ROW][COL], int row, int col) {
    for (int i = 0; i < row; i++)
    {
        if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        {
            return board[i][0];
        }
    }
    for (int i = 0; i < col; i++)
    {
        if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
        {
            return board[0][i];
        }
    }
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    {
        return board[1][1];
    }
    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
    {
        return board[1][1];
    }
    is_full(board, ROW, COL);
}


这里我们返回符合条件的*或者#,在game()函数中判断返回值,即可判断胜利


game()函数

使用一个循环,如果有一方胜利或者平局则打破循环结束游戏

void game() {
    char board[ROW][COL];
    char res = 0;
    Init(board, ROW, COL);
    print(board, ROW, COL);
    while (1) {
        player_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        Sleep(1000);
        computer_move(board, ROW, COL);
        print(board, ROW, COL);
        is_win(board, ROW, COL);
        res= is_win(board, ROW, COL);
        if (res == '*') {
            printf("玩家胜!\n");
            break;
        }
        else if(res=='#') {
            printf("AI胜!\n");
            break;
        }
    }
}


总结


在写代码的过程中,遇到问题解决问题是提升最快的方式。


当你碰到不会的,不懂的,不要害怕,这正是你所能够进步的地方!


我是分模块写的,源码如下:


fun.c


#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
void memu() {
  printf("********************************\n");
  printf("************* 1->开始 **********\n");
  printf("************* 0->退出 **********\n");
  printf("********************************\n");
  printf("->");
}
void game() {
  char board[ROW][COL];
  char res = 0;
  Init(board, ROW, COL);
  print(board, ROW, COL);
  while (1) {
  player_move(board, ROW, COL);
  print(board, ROW, COL);
  is_win(board, ROW, COL);
  Sleep(1000);
  computer_move(board, ROW, COL);
  print(board, ROW, COL);
  is_win(board, ROW, COL);
  res= is_win(board, ROW, COL);
  if (res == '*') {
    printf("玩家胜!\n");
    break;
  }
  else if(res=='#') {
    printf("AI胜!\n");
    break;
  }
  }
}
void Init(char board[ROW][COL], int row, int col) {
  for (int i=0; i < row; i++) {
  for (int j=0; j < col; j++) {
    board[i][j] = ' ';
  }
  }
}
void print(char board[ROW][COL], int row, int col) {
  for (int i = 0; i < row; i++) {
  for (int j = 0; j < col; j++) {
    printf(" %c ", board[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");
  }
  }
}
void player_move(char board[ROW][COL], int row, int col) {
  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");
  }
  }
}
void computer_move(char board[ROW][COL], int row, int col) {
  printf("AI下棋:\n");
  while (1) {
  is_full(board, ROW, COL);
  int x = rand() % row;
  int y = rand() % col;
  if (board[x][y] == ' ') {
    board[x][y] = '#';
    break;
  }
  }
}
char is_win(char board[ROW][COL], int row, int col) {
  for (int i = 0; i < row; i++)
  {
  if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
  {
    return board[i][0];
  }
  }
  for (int i = 0; i < col; i++)
  {
  if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
  {
    return board[0][i];
  }
  }
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
  {
  return board[1][1];
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
  {
  return board[1][1];
  }
  is_full(board, ROW, COL);
}
void is_full(char board[ROW][COL], int row, int col) {
  int flag = 0;
  for (int i = 0; i < row; i++) {
  for (int j = 0; j < col; j++) {
    if (board[i][j] == ' ') {
    flag++;
    }
  }
  }
  if (flag == 0) {
  printf("平局\n");
  exit(0);
  }
}
main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "sanziqi.h"
int main() {
  memu();
  srand((unsigned int)time(NULL));
  int input;
  scanf("%d", &input);
  switch(input) {
  case 0:
  exit(0);
  break;
  case 1:
  game();
  break;
  default:
  printf("输入错误!");
  break;
  }
}
sanziqi.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 3
#define COL 3
void memu();//菜单
void game();//进入游戏
void Init(char board[ROW][COL], int row, int col);//初始化
void print(char board[ROW][COL],int row,int col);//打印界面
void player_move(char board[ROW][COL], int row, int col);//玩家下棋
void computer_move(char board[ROW][COL], int row, int col);//AI下棋
char is_win(char board[ROW][COL], int row, int col);//判断胜利
void is_full(char board[ROW][COL], int row, int col);//判断是否填满,平局
相关文章
|
6月前
|
C语言
以c语言为基础实现的简易三子棋
以c语言为基础实现的简易三子棋
40 1
|
6月前
|
C语言
c语言简单三子棋
c语言简单三子棋
|
6月前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
59 1
|
6月前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
6月前
|
C语言
用c语言实现三子棋
用c语言实现三子棋
26 0
|
5月前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
30 1
|
6月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
68 1
|
6月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
78 1
|
6月前
|
编译器 C语言
【C语言入门小游戏】三子棋
【C语言入门小游戏】三子棋
52 0
【C语言入门小游戏】三子棋
|
5月前
|
存储 C语言
三子棋(C语言版)
三子棋(C语言版)