井字游戏也被称为"Noughts和crosses"。它是两个玩家最普遍的纸笔游戏之一。

它主要由年幼的孩子放置,但很多时候,你也可以看到成年人玩这个来切断无聊。这个游戏非常方便,可以在任何地方玩,只有两个玩家。每个玩家必须在 X 和 O 之间选择一个符号。游戏在3×3网格中进行。每个玩家每回合只能放置一个符号,然后该回合被传递给另一个玩家。

游戏范式:

  • 优胜: 每个玩家都尝试将他们的三个符号放置在三个相邻的水平,垂直或对角线单元格中。更早实现这种一致性的人是赢家。当第二个玩家试图通过在玩家1的符号之间放置自己的符号来中断玩家1的对齐时。
  • 失去: 如果您的竞争对手首先获得所需的符号对齐方式,那么您将失败。
  • 画: 如果抓地力的所有九个单元格都已标记,并且没有一个玩家,则可实现所需的对齐。条件是平局或平局。在这种情况下,没有一个球员得到一分。这种情况在游戏过程中发生了无数次,实际上很有趣。

由于其简单性,井字棋被认为是向儿童教授逻辑构建和体育精神的完美教学工具。从技术上讲,还有更多功能,您可以使用人工智能创建一个游戏树,向您展示符号和单元格的所有组合的可能性。如果游戏由两个玩家以最佳方式进行,则游戏将以平局结束。这使得井字棋成为一种徒劳的游戏。

刻板的3 x 3双色井字棋可以修改为p,q,d颜色游戏,其中两个玩家交替将他们的符号放在p x q板上,目标是在垂直,水平或对角线上获得自己颜色的d。

让我们学习使用Kotlin类在Android Studio中创建井字游戏应用的步骤

第一阶段设计:

图片来源:截图来自Android Emulator

步骤 1:创建网格布局

在属性 rowCount 和 columnCount 中,输入值 3,这样网格中就有三行和三列。在>>可绘制文件夹中添加方形网格的图像资产。将图像另存为 tictac。在背景属性中,指定图像的位置。

用于创建网格
图像的示例图像 来源:Google

网格布局的 XML 代码:

<GridLayoutandroid:layout_width="350dp"android:layout_height="350dp"android:layout_marginLeft="30dp"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="49dp"android:background="@drawable/tictac"android:columnCount="3"android:rowCount="3"android:id="@+id/gridLayout">
</GridLayout>

步骤 2:处理交易品种

在应用程序中添加两个图像资产,>>可绘制文件夹。您可以将它们另存为 circle1 和 circle2。最终,图像资源设置为 0,这意味着 null。每个图像视图都是在网格的单元格中创建的,这意味着总共需要九个图像视图。

玩家 1 的符号

玩家 1 的符号(您可以使用十字架代替)

要点:

  • 确保使它们可点击。在单击图像视图时调用方法"dropIn"android:onClick="dropIn"
  • 为每个行号和列号指定它们。android:layout_row="2" android:layout_column="1"
  • 向每个图像视图添加唯一的标记。安卓:标签="7"

当玩家点击单元格时,圆圈被放置在单元格中。
图片来源:截图来自Android Emulator

步骤 3:显示结果

一旦两个玩家中的任何一个获胜,文本视图变得可见,我们就可以将文本设置为"绿色获胜"或"红色获胜"。如果没有玩家获胜,并且网格的所有九个单元格都被标记,则将TextView的文本设置为"Draw"。

只有在进入三种情况中的任何一种情况后,文本视图才会设置为可见,并且与此一起,"再次播放"按钮也变得可见。"再次播放"按钮调用"重玩"功能;它清除网格单元格的图像,并将所有变量重置为其初始值。

这是图像中提到的UI设计的完整XML代码;此代码以 activity_main.xml 编写:<?xml version="1.0" encodi

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><GridLayoutandroid:layout_width="350dp"android:layout_height="350dp"android:layout_marginLeft="30dp"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="49dp"android:background="@drawable/tictac"android:columnCount="3"android:rowCount="3"android:id="@+id/gridLayout"><ImageViewandroid:id="@+id/imageView"android:layout_width="70dp"android:layout_height="70dp"android:layout_marginLeft="25dp"android:layout_marginTop="25dp"android:layout_row="0"android:layout_column="0"android:onClick="dropIn"android:tag="0"/><ImageViewandroid:id="@+id/imageView2"android:layout_width="70dp"android:layout_height="70dp"android:layout_column="1"android:layout_marginLeft="35dp"android:layout_marginTop="25dp"android:layout_row="0"android:onClick="dropIn"android:tag="1"/><ImageViewandroid:id="@+id/imageView3"android:layout_width="70dp"android:layout_height="70dp"android:layout_column="2"android:layout_marginLeft="35dp"android:onClick="dropIn"android:layout_marginTop="25dp"android:layout_row="0"android:tag="2"/><ImageViewandroid:id="@+id/imageView4"android:layout_width="70dp"android:layout_height="70dp"android:layout_column="0"android:layout_marginLeft="25dp"android:onClick="dropIn"android:layout_marginTop="40dp"android:layout_row="1"android:tag="3"/><ImageViewandroid:id="@+id/imageView5"android:layout_width="70dp"android:layout_height="70dp"android:layout_column="1"android:layout_marginLeft="35dp"android:onClick="dropIn"android:layout_marginTop="40dp"android:layout_row="1"android:tag="4"/><ImageViewandroid:id="@+id/imageView6"android:layout_width="70dp"android:layout_height="70dp"android:layout_column="2"android:onClick="dropIn"android:layout_marginLeft="35dp"android:layout_marginTop="40dp"android:layout_row="1"android:tag="5"/><ImageViewandroid:id="@+id/imageView7"android:layout_width="70dp"android:layout_row="2"android:layout_column="0"android:layout_height="70dp"android:onClick="dropIn"android:layout_marginLeft="25dp"android:layout_marginTop="45dp"android:tag="6"/><ImageViewandroid:id="@+id/imageView8"android:layout_width="70dp"android:layout_height="70dp"android:layout_row="2"android:layout_column="1"android:onClick="dropIn"android:layout_marginLeft="40dp"android:layout_marginTop="40dp"android:tag="7"/><ImageViewandroid:id="@+id/imageView9"android:layout_width="70dp"android:layout_height="70dp"android:layout_row="2"android:layout_column="2"android:onClick="dropIn"android:layout_marginLeft="35dp"android:layout_marginTop="45dp"android:tag="8" /></GridLayout><LinearLayoutandroid:id="@+id/winner"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_centerHorizontal="true"android:orientation="vertical"android:padding="20dp"android:visibility="invisible"><TextViewandroid:id="@+id/winner1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="Winner"android:layout_gravity="center"android:textSize="24sp"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="PLAY Again?"android:onClick="playAgain"/></LinearLayout>
</RelativeLayout>
</code></span></span>

第二阶段:Kotlin 类

构成变量:

状态:我们将每个单元格的状态存储在称为gameState的变量中。最初,每个单元格的状态为 2。如果单元格由绿色圆圈标记,即玩家 1 的移动,则该单元格的 gameState 为 1。而如果单元格由红色圆圈标记,则这是玩家 2 的移动,则该单元格的游戏状态为 0。gameState是一个整数数组,它可以存储所有9个单元格的状态。用户无法标记已标记的单元格;在 gameState 变量的帮助下检查此条件。

活跃玩家:变量activePlayer指示谁的回合正在进行中。每次移动后,该值在0和1之间切换,因为不允许任何玩家在游戏中连续移动两次。

游戏处于活动状态:它是一个布尔变量,表示游戏处于活动状态或休眠状态。如果任何玩家获胜或平局,则 gameIsActive 变量将设置为 false。当单击"再次播放"按钮时,它将再次设置为 true。

计数变量:它存储已标记的单元格数量的值。当没有一个玩家获胜并且计数变为九时,游戏是平局比赛。单击"再次播放"按钮时,计数变量的值将变为零。在每个玩家的每次后续移动之后,计数变量都会递增一。

获胜仓位:我们创建一个由九个整数数组组成的数组。这些子整数数组包含获胜仓位的索引组合。垂直行、水平行和对角线行的所有可能组合都存在于获胜位置中。因此,如果这三个单元格中的任何一个被两个玩家中的任何一个标记,他或她就赢了。

获胜位置集: (0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6).

Kotlin类中编写了两个主要函数:

dropIn:当用户单击网格的九个单元格中的任何一个时,将调用它。之后,每一步棋,玩家的标记位置都会与获胜组合的集合进行比较,如果任何条件匹配,则该玩家被宣布为获胜者。添加了其他动画,用于平滑网格视图中红色和绿色圆圈的滑动。

平局条件:如果没有一个玩家能够标记任何获胜位置,并且还标记了单元格,则游戏是平局。如果计数变量达到 9 并且游戏仍处于活动状态,则由计数变量的值指示。游戏已停止,因此布尔变量设置为 false,显示的结果是 DRAW,因此文本视图也变得可见。

if (gameIsActive && count == 9) {txt.text = "DRAW"layout.visibility = View.VISIBLEgameIsActive = false}

重玩:当用户单击"再次播放"按钮时,将调用它。此功能的主要目的是在玩完一轮游戏后重置所有变量。此函数将 count 的值设置为零,将玩家 1 设置为活动玩家,使游戏处于活动状态,将网格的所有单元格的状态设置为 2(既不是红色也不是绿色),并清除在上一个游戏中设置的所有图像资源。这是必要的,以便先前变量值的交替不会干扰当前的博弈。

fun playAgain(view: View?)
{activePlayer = 1gameIsActive = truecount= 0val linearLayout = findViewById<LinearLayout>(R.id.winner)val gridLayout =findViewById<GridLayout>(R.id.gridLayout)for (i in gameState.indices){gameState[i] = 2}linearLayout.visibility = View.INVISIBLEfor (i in 0 until gridLayout.childCount){(gridLayout.getChildAt(i) as ImageView).setImageResource(0) }
}

Tic-Tac-Toe应用程序的完整MainActivity.kt代码:

package com.example.tic_tac_toe;
import android.os.Bundle
import android.view.View
import android.widget.GridLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity() {//1=green  0 =redvar activePlayer = 1var gameIsActive = truevar count = 0var gameState = intArrayOf(2, 2, 2, 2, 2, 2, 2, 2, 2)var winningPositions = arrayOf(intArrayOf(0, 1, 2),intArrayOf(3, 4, 5),intArrayOf(6, 7, 8),intArrayOf(0, 3, 6),intArrayOf(1, 4, 7),intArrayOf(2, 5, 8),intArrayOf(0, 4, 8),intArrayOf(2, 4, 6))fun dropIn(view: View) {val counter = view as ImageViewval txt = findViewById<TextView>(R.id.winner1)val layout = findViewById<LinearLayout>(R.id.winner)//understandval tappedcounter = counter.tag.toString().toInt()if (gameState[tappedcounter] == 2 && gameIsActive) {if (activePlayer == 1) {counter.setImageResource(R.drawable.circle1)activePlayer = 0count++gameState[tappedcounter] = 1} else {counter.setImageResource(R.drawable.circle2)activePlayer = 1count++gameState[tappedcounter] = 0}counter.translationY = -1000fcounter.animate().translationYBy(1000f).rotationY(1800f).duration = 1000for (winningposition in winningPositions) {if (gameState[winningposition[0]] == gameState[winningposition[1]] && gameState[winningposition[1]] == gameState[winningposition[2]] && gameState[winningposition[0]] != 2) {if (gameState[winningposition[0]] == 0) txt.text ="Red Player Wins" else if (gameState[winningposition[0]] == 1) txt.text = "Green Player Wins"layout.visibility = View.VISIBLEgameIsActive = false}}}if (gameIsActive && count == 9) {txt.text = "DRAW"layout.visibility = View.VISIBLEgameIsActive = false}}fun playAgain(view: View?) {activePlayer = 1gameIsActive = truecount= 0val linearLayout = findViewById<LinearLayout>(R.id.winner)val gridLayout =findViewById<GridLayout>(R.id.gridLayout)for (i in gameState.indices) {gameState[i] = 2}linearLayout.visibility = View.INVISIBLEfor (i in 0 until gridLayout.childCount) {(gridLayout.getChildAt(i) as ImageView).setImageResource(0) //p t n}}protected override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)}
}

尝试自己实现代码。你练习得越多,你的概念就越完美。如果需要,可以通过更改网格布局的行和列计数来修改单元格数。

使用Kotlin在Android Studio中创建井字游戏相关推荐

  1. android studio建数据库表,在android studio中创建表

    错误:android.database.sqlite.SQLiteException:表用户没有列名(代码1):编译时:INSERT INTO用户名(名称,余额,密码,年龄)VALUES(? ?,?, ...

  2. 在 Android Studio 中创建一个简单的 QQ 登录界面

    一,创建一个新的 Android Studio 项目 打开 Android Studio,选择 "Start a new Android Studio project",然后填写应 ...

  3. android studio中创建、切换svn分支

    偶尔翻到一篇之前的笔记,虽然早已经从svn专用git了,但还是分享出来给那些还坚守svn的小伙伴吧. 相对于git,svn的分支管理就没那么简单方便,所以总结一些在Android Studio上使用s ...

  4. android studio创建文件,如何在Android Studio中创建File Templates

    标签: File Template Android Studio 我发现一个可以让写程序变得简单的方法,那就是自定义文件模板(Custom File Templates).那么什么是File Temp ...

  5. android flutter 环境,Android Studio 中创建Flutter环境配置(Mac环境)

    1.先下载Flutter 的SDK ,网页中有打包好的SDK(https://flutter.io/setup-macos/) 2.设置PATH 代码下载之后在终端中打开bash_profile文件 ...

  6. 在android studio中创建Hello-JNI工程

    2019独角兽企业重金招聘Python工程师标准>>> 1. Overview What you'll need : Android Studio 2.2 or higher fro ...

  7. 在android studio中如何创建一个类来继承另外一个类_在Android使用Transition API检测用户活动...

    在当今世界,移动设备是我们日常生活中必不可少的一部分,我们在走路.跑步.开车以及其他许多活动时都会使用移动设备. 了解用户拿着手机的时候在做什么,可以让你的应用程序根据用户的动作进行直观的调整.对于某 ...

  8. android studio 自定义字体,Android Studio中的自定义字体

    如何在android studio中创建自定义字体? 我试图使用自定义字体,我读过,我想将字体放在资产/字体. 我已经搜索了很长时间,但很难找到帮助. 我哪里错了?我真的不知道该怎么做. 我写下了所有 ...

  9. android studio中把c/c++文件编译成.so库(一)

    2019独角兽企业重金招聘Python工程师标准>>> 最近的项目涉及到JNI编程,经过一段时间的JNI编程之后,终于完美弄完了.所以,把在android studio中编译c/c+ ...

最新文章

  1. 学校计算机培训管理制度,小学教师信息技术培训管理制度
  2. 源码安装vsftp3.0.3
  3. iOS10 UI教程禁用视图与用户的交互
  4. 细数 Spring 那些最常见的面试问题
  5. 英特尔推出全新至强处理器E5 v4产品家族
  6. 什么情况下会调用到session_destroy()
  7. java的Random类详解
  8. 多媒体分析与理解_如何设计一个出色的数字多媒体展厅?
  9. Android Audio Play Out Channel
  10. ARM指令集之乘法指令
  11. ipad横屏怎么设置方法,如何使ipad横屏
  12. 纹理特征提取(envi+python)
  13. 你要问我应用层?我就和你扯扯扯
  14. 人生就像四季,繁华过后终归平淡,不可能一直繁华似锦,不可能一路花香四溢。...
  15. 在Android运行cocos Demo游戏
  16. c语言程序 计算离高考天数,用c++程序计算一个孩子从出生到高考需要多少天
  17. 酷盟集团旗下酷客SCRM亮相2020 CBME孕婴童展
  18. flink java快速上手
  19. 单电源运放全波整流电路
  20. 登高车的使用注意事项及具体操作步骤有哪些?

热门文章

  1. 行车记录仪格式化了还能恢复吗?
  2. java怎么调epass3003,Snooper.Spec-003-apdu脚本_taoism版.pdf
  3. MES人事管理系统源码
  4. 如何写优雅的代码(1)——灵活使用goto和__try:评论反馈
  5. 用户运营中,培养种子用户的三种模式
  6. java 蓝桥杯 黄金队列
  7. EXCEL批量打开超链接
  8. 深度强化学习Soft-Actor Critic算法高性能Pytorch代码(改写自spinningup,低环境依赖,低阅读障碍)
  9. 新旧系统更替产生的数据迁移问题
  10. CentOS 7一键安装Seafile搭建私有云存储