当前位置: 首页 > article >正文

angular舒尔特方格

说明:我计划用angular实现舒尔特方格的功能,必须是动态的,比如33,55,9*9,而且无论是什么样式的,都必须保持正方形,然后还有时间监听,计算用户完成方格的时间,

另外,我还需要优化ui样式,让它变得好看,增加背景,圆角和悬停效果,还可以加一点小动画,让它看起来更加美观,下面给出完整代码
效果图:
在这里插入图片描述

step1: C:\Users\Administrator\WebstormProjects\untitled4\src\app\schulte\schulte.component.ts

import { Component ,OnDestroy,OnInit} from '@angular/core';
import {NgForOf, NgIf} from '@angular/common';

@Component({
  selector: 'app-schulte',
  imports: [NgForOf, NgIf],
  templateUrl: './schulte.component.html',
  styleUrl: './schulte.component.css'
})
export class SchulteComponent  implements OnDestroy,OnInit{

  gridSize = 4;
  numbers: number[] = [];
  currentNumber = 1;
  timeUsed = 0;
  isStarted = false;
  private timer: number | undefined;
  gridStyle = {};

  ngOnInit() {
    this.initializeGame();
    this.updateGridStyle();
  }

  private initializeGame() {
    const size =this.gridSize ** 2;
    this.numbers = Array.from({ length: size }, (_, i) => i + 1);

    // Fisher-Yates shuffle
    for (let i = this.numbers.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [this.numbers[i], this.numbers[j]] = [this.numbers[j], this.numbers[i]];
    }
  }

  updateGridStyle() {
    const cellSizePercentage = 100 / this.gridSize;
    const fontSize = Math.min(4 / this.gridSize, 1.2);

    this.gridStyle = {
      'gridTemplateColumns': `repeat(${this.gridSize}, 1fr)`,
      'fontSize': `${fontSize}rem`
    };
  }

  startGame() {
    this.clearTimer();
    this.isStarted = true;
    this.currentNumber = 1;
    this.timeUsed = 0;

    this.timer = window.setInterval(() => {
      this.timeUsed++;
    }, 1000);
  }

  handleClick(num: number) {
    if (!this.isStarted) return;

    if (num === this.currentNumber) {
      this.currentNumber++;
      if (this.currentNumber > this.gridSize ** 2) {
        this.gameComplete();
      }
    } else {
      this.handleError();
    }
  }

  private gameComplete() {
    this.clearTimer();
    alert(`🎉 完成时间: ${this.timeUsed}`);
    this.isStarted = false;
    this.initializeGame();
  }

  private handleError() {
    this.clearTimer();
    this.isStarted = false;
    alert('❌ 点错数字,重新开始!');
    this.initializeGame();
  }

  private clearTimer() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = undefined;
    }
  }

  ngOnDestroy() {
    this.clearTimer();
  }


}

step2: C:\Users\Administrator\WebstormProjects\untitled4\src\app\schulte\schulte.component.html

<div class="game-container">
  <button *ngIf="!isStarted"
          class="start-btn"
          (click)="startGame()">
    🚀 开始挑战
  </button>

  <div class="status-box">
    <div class="status-item">
      <span class="label">当前数字</span>
      <span class="value">{{ currentNumber }}</span>
    </div>
    <div class="status-item">
      <span class="label">用时</span>
      <span class="value">{{ timeUsed }}s</span>
    </div>
  </div>

  <div class="grid" [style]="gridStyle">
    <button
      *ngFor="let num of numbers"
      (click)="handleClick(num)"
      [disabled]="!isStarted"
      class="grid-btn"
      [class.active]="num === currentNumber"
    >
      {{ num }}
    </button>
  </div>
</div>

step3: C:\Users\Administrator\WebstormProjects\untitled4\src\app\schulte\schulte.component.css

.game-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  padding: 2rem;
  background: #f8f9fa;
  border-radius: 1.5rem;
  box-shadow: 0 8px 30px rgba(0,0,0,0.1);
  max-width: 95vw;
  margin: 2rem auto;
}

.start-btn {
  padding: 1rem 2.5rem;
  font-size: 1.2rem;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: white;
  border: none;
  border-radius: 0.75rem;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
}

.start-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
}

.status-box {
  display: flex;
  gap: 2rem;
  padding: 0.8rem 1.5rem;
  background: white;
  border-radius: 0.75rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}

.status-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.label {
  font-size: 0.9rem;
  color: #6b7280;
}

.value {
  font-size: 1.2rem;
  font-weight: 600;
  color: #1f2937;
}

.grid {
  display: grid;
  gap: 0.5rem;
  width: 80vmin;
  height: 80vmin;
  max-width: 600px;
  max-height: 600px;
  padding: 1rem;
  background: white;
  border-radius: 1rem;
  box-shadow: inset 0 2px 8px rgba(0,0,0,0.05);
}

.grid-btn {
  aspect-ratio: 1;
  border: none;
  border-radius: 0.5rem;
  background: linear-gradient(145deg, #f3f4f6, #e5e7eb);
  color: #1f2937;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.grid-btn:hover:not(:disabled) {
  background: linear-gradient(145deg, #e5e7eb, #d1d5db);
  transform: scale(1.03);
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}

.grid-btn.active {
  background: linear-gradient(145deg, #c7d2fe, #a5b4fc);
  color: #4338ca;
  transform: scale(0.98);
}

.grid-btn:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

end


http://www.kler.cn/a/563434.html

相关文章:

  • 医院HIS接入大模型:算力基础设施与训练能力的深度剖析与测算
  • Docker基础-常见命令
  • 面试之《react中,fiber更新时,怎么判断fiber是否应该在当前idle内执行》
  • osgEarth安装总结
  • 将夸克网盘的webdav挂载成本地磁盘驱动器时报错“405“
  • 学习汇编前置知识第二天
  • nginx代理后502
  • seacmsv9 SQL注入漏洞
  • DFS:二叉树的深搜与回溯
  • 冒泡排序(Bubble Sort)详细教程:Java实现与优化
  • Python使用列表实现栈、队列学习记录
  • 【C++修炼之路】C++类与对象:面向对象编程的第一步
  • 字节火山引擎-大模型声音复刻,流式语音合成接口
  • Linux网络之传输层协议(UDP,TCP协议)
  • OpenGL ES -> GLSurfaceView绘制点、线、三角形、正方形、圆(顶点法绘制)
  • 【Python爬虫(82)】开启物联网数据爬取之旅
  • 下载commons-io-jar 2.6版本
  • [特殊字符]️ ‌Selenium元素存在性判断的5种方法‌
  • string类详解(下)
  • 自定义ToolbarView实战指南(Kotlin版)