鸿蒙初体验-五子棋
Posted 雪飘七月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鸿蒙初体验-五子棋相关的知识,希望对你有一定的参考价值。
一、鸿蒙系统
鸿蒙正式上线已经两个多月,最近才有时间来体验。鸿蒙拥有自己的开发工具DevEco Studio,我们需要去官网下载安装。DevEco Studio是一款基于Idea的编辑器。
鸿蒙的UI分为Java UI框架和JS UI框架。Java UI框架更类似于android的原生UI,而JS UI更类似于VUE的web前端UI。
二、新建工程
File->New->New Project进入如下界面:
我这里选择的是第一个Empty Ability(JS),这里我是确定用JS UI框架选择的这个模板工程。
创建后工程目录如下:
创建后有默认的hello world可以运行,但是我不管是模拟器和实机都没有跑起来。
三、模拟器
Tools->Device Manager
这里可以选择启动想要的模拟器设备,但是首次使用的时候需要登录实名认证过的华为开发者账号才能有设备列表。
选择对应的设备就能启动模拟器,然后点击run按钮就能启动工程。
这里要注意的是,工程中有一个config.json,其中有一段配置deviceType,需要工程配置对应的设备才能启动。
"deviceType": [
"phone",
"tv"
],
四、实机运行
实机运行的话首先要实名认证华为开发者,然后在AppGallery Connect中建立对应的项目和应用,应用中有包名需要登记,这个包名需要与我们的工程包名统一。
然后Studio中 File->Project Structure->Project->Signing Configs,
这里登录华为开发者实名认证过的账号,就能自动拉取认证信息。
这时候选中我们的实机,然后run就可以运行程序到我们的实机上了。
五、五子棋
下面我们做个五子棋demo
主要修改js下的pages
index.hml
<div class="container">
<div class="left">
<div class="avatar">
<image src="/common/images/1.jpg"></image>
</div>
<text>我</text>
</div>
<canvas ontouchstart="onPressChess"
id="chess" class="chess"
style="width: {{ canvasWidth }}px; height: {{ canvasHeight }}px;"></canvas>
<div class="right">
<div class="avatar">
<image src="/common/images/2.jpg"></image>
</div>
<text>AI</text>
</div>
<div class="send">-->
<button class="btn" onclick="reset">重新开始</button>
</div>
</div>
index.css
.container {
display: flex;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-image: url(\'/common/images/bg.png\');
background-size: 100% 100%;
flex-direction: row;
}
@media screen and (device-type: tv) {
.container {
background-image: url(\'/common/images/bg2.png\');
}
.left {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 250px;
padding: 10px;
margin-right: 3px;
background-color: gray;
opacity: 1;
}
.right {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 250px;
padding: 10px;
margin-right: 3px;
background-color: gray;
opacity: 1;
}
.avatar {
width: 100px;
height: 100px;
border-radius: 50px;
}
}
@media screen and (device-type: phone) {
.left {
display: none;
}
.right {
display: none;
}
}
.send {
width: 400px;
height: 50px;
border-radius: 25px;
position: absolute;
top: 50px;
left: 50px;
}
.btn {
padding: 10px;
}
index.js
import router from \'@system.router\';
import prompt from \'@system.prompt\';
export default {
data: {
cxt:{},
rowLineNum:15, //行数
colLineNum:15, //列数
boxSize:30, //宽和高一样
canvasWidth:12*30,
canvasHeight:15*30,
lineNum:12, //行数和列数一样
canvasSize:360, //宽和高一样
boxPadding:15, //内边距
me:true, //判断是否是自己
over:false, //判断游戏是否已结束
chessboard:[], //棋盘数组
myWin:[], //自己的赢法统计
computerWin:[], //对方的赢法统计
wins:[], //所有的赢法统计
count:0, //赢法统计
},
onShow() {
this.cxt = this.$element("chess").getContext("2d");
this.drawBoardBackground();
},
drawBoardBackground() {
var img = new Image();
img.src = "/common/images/1.jpg";
img.onload = () =>{
// this.cxt.drawImage(img,0,0,this.canvasWidth,this.canvasHeight+this.boxSize);
this.drawRectangleBoard();
}
},
drawRectangleBoard() {
for( let index=0 ; index < this.rowLineNum ;index++ ){
//横线,x轴不变,y轴变化
this.cxt.beginPath();
this.cxt.moveTo(this.boxPadding,this.boxPadding+index*this.boxSize);
this.cxt.lineTo(this.canvasSize-this.boxPadding,this.boxPadding+index*this.boxSize);
this.cxt.closePath();
this.cxt.stroke();
}
for( let index=0 ; index < this.colLineNum ;index++ ){
//横线,x轴变化,y轴不变
this.cxt.beginPath();
this.cxt.moveTo(this.boxPadding+index*this.boxSize,this.boxPadding);
this.cxt.lineTo(this.boxPadding+index*this.boxSize,this.canvasHeight-this.boxPadding);
this.cxt.closePath();
this.cxt.stroke();
}
},
onInit() {
this.initWinGroup();
this.initChessData();
},
initWinGroup(){
//初始化赢法数组x、y、groupid(第几组赢法)
for(var i=0;i<this.rowLineNum;i++){
this.wins[i] = []
for(var j=0;j<this.rowLineNum;j++){
this.wins[i][j] = []
}
}
//记录x赢法数组
for(var i=0;i<this.rowLineNum;i++){
for(var j=0;j<this.rowLineNum-4;j++){
for(var k=0;k<5;k++){
this.wins[j+k][i][this.count] = true
}
this.count++
}
}
//记录y赢法数组
for(var i=0;i<this.rowLineNum;i++){
for(var j=0;j<this.rowLineNum-4;j++){
for(var k=0;k<5;k++){
this.wins[i][j+k][this.count] = true
}
this.count++
}
}
//正斜线赢法数组
for(var i=0;i<this.rowLineNum-4;i++){
for(var j=0;j<this.rowLineNum-4;j++){
for(var k=0;k<5;k++){
this.wins[i+k][j+k][this.count] = true
}
this.count++
}
}
//反斜线赢法数组
for(var i=0;i<this.rowLineNum-4;i++){
for(var j=this.rowLineNum-1;j>3;j--){
for(var k=0;k<5;k++){
this.wins[i+k][j-k][this.count] = true
}
this.count++
}
}
},
initChessData(){
for(var i=0; i<this.rowLineNum ;i++){
this.chessboard[i] = []
for(var j=0; j<this.rowLineNum;j++){
this.chessboard[i][j] = 0
}
}
for(let index=0; index<this.count;index++){
this.myWin[index] = 0;
this.computerWin[index] = 0;
}
},
onPressChess(e){
//游戏是否已结束
if(this.over){
return
}
//如果不是我,则直接返回
if(!this.me){
return
}
let x = Math.floor(e.touches[0].localX/this.boxSize)
let y = Math.floor(e.touches[0].localY/this.boxSize)
//判断当前位置是否有棋子,0标识没有,1表示有
if(this.chessboard[x][y] == 0){
//在x和y这个位置画棋子
this.drawChess(x,y);
//判断是否赢了
this.checkWin(x,y);
//如果游戏没有结束,则当前是个开关,AI计算机可继续下棋子
if(!this.over){
this.me = !this.me;
this.computerAI()
}
}
},
drawChess(x,y){
console.info("=====drawChess x:"+ x + " y:"+y);
//每次落子之前,把x和y的位置设置为1,这个位置下次不能落子,这个很重要
this.chessboard[x][y] = 1
var px = this.boxPadding + x*this.boxSize;
var py = this.boxPadding + y*this.boxSize;
this.cxt.beginPath();
this.cxt.arc(px, py,13,0,2*Math.PI)
this.cxt.closePath();
if(!this.me){
this.cxt.fillStyle = "white"
}else{
this.cxt.fillStyle = "black"
}
this.cxt.fill();
},
checkWin(x,y){
for(var index =0; index < this.count ;index++){
if(this.wins[x][y][index]){
//如果是自己,则在自己的统计中添加次数
if(this.me){
this.myWin[index] += 1;
if(this.myWin[index] == 5){
this.over = true;
prompt.showToast({
message:"恭喜,你赢了!",
duration:3000
})
}
}else{
this.computerWin[index] += 1;
if(this.computerWin[index] == 5){
this.over = true;
prompt.showToast({
message:"ooss,你输了!",
button:[
{
text:\'重新再来\',
color:\'#666666\',
}
],
success: function(data){
router.push({
uri:"pages/chess/chess"
})
},
cancel:function(){
console.info(\'dialog cancel callback\');
},
});
}
}
}
}
},
computerAI(){
//计算每个子所在的分值
var myScore = []
var computerScore = []
for(var i=0;i<this.rowLineNum;i++){
myScore[i] = []
computerScore[i] = []
for(var j=0;j<this.rowLineNum;j++){
myScore[i][j] = 0
computerScore[i][j] = 0
}
}
//打分
var maxScore = 0;
var maxX = 0;
var maxY = 0;
//计算maxscore
for(var i=0;i<this.rowLineNum;i++){
for(var j=0;j<this.rowLineNum;j++){
//计算计算机最优的下子位置
//棋盘上没有下子的位置
if(this.chessboard[i][j] == 0){
for(var k=0;k<this.count;k++){
if(this.wins[i][j][k]){
//me
if(this.myWin[k] == 1){
myScore[i][j] += 200
}else if(this.myWin[k] == 2){
myScore[i][j] += 400
}else if(this.myWin[k] == 3){
myScore[i][j] += 1000
}else if(this.myWin[k] == 4){
myScore[i][j] += 10000
}
//computer
if(this.computerWin[k] == 1){
computerScore[i][j] += 220
}else if(this.computerWin[k] == 2){
computerScore[i][j] += 440
}else if(this.computerWin[k] == 3){
computerScore[i][j] += 1600
}else if(this.computerWin[k] == 4){
computerScore[i][j] += 30000
}
}
}
//拦截
// @ts-ignore
if(myScore[i][j] > maxScore){
maxScore = myScore[i][j];
maxX = i;
maxY = j;
}else if(myScore[i][j] == maxScore){
// @ts-ignore
if(computerScore[i][j] > maxScore){
maxX = i;
maxY = j;
}
}
//落子
// @ts-ignore
if(computerScore[i][j] > maxScore){
maxScore = computerScore[i][j];
maxX = i;
maxY = j;
}else if(computerScore[i][j] == maxScore){
// @ts-ignore
if(myScore[i][j] > maxScore){
maxX = i;
maxY = j;
}
}
}
}
}
this.drawChess(maxX,maxY);
this.checkWin(maxX,maxY);
if(!this.over){
this.me = !this.me
}
},
clearCanvas() {
this.cxt.clearRect(0,0,this.canvasWidth,this.canvasHeight+this.boxSize);
},
reset(){
this.over = false;
this.me = true;
this.clearCanvas();
this.onShow();
this.onInit();
},
}
以上是五子棋的代码,其中包含了一个简单AI,直接run就可以运行,以下是在TV和P40模拟器中的运行结果:
以上是关于鸿蒙初体验-五子棋的主要内容,如果未能解决你的问题,请参考以下文章
《 HarmonyOS实战—HarmonyOS(鸿蒙)开发初体验,华为如何引领物联网时代》
《 HarmonyOS实战—HarmonyOS(鸿蒙)开发初体验,华为如何引领物联网时代》