console
class operation {
constructor(level, sign, a, b) {
this.level = level;
this.sign = sign;
this.stra = a.toString();
this.strb = b.toString();
if (Number.isInteger(a)){
this.a = a;
} else {
this.a = a.calc();
if (a.level < level) {
this.stra = `( ${this.stra} )`;
}
}
if (Number.isInteger(b)){
this.b = b;
} else {
this.b = b.calc();
if (b.level <= level) {
this.strb = `( ${this.strb} )`;
}
}
}
calc() {}
toString() {
return `${this.stra} ${this.sign} ${this.strb}`;
}
}
class add extends operation {
constructor(a, b) {
super(1, '+', a, b);
}
calc() {
if (isNaN(this.a) || isNaN(this.b)){
return NaN;
} else {
return this.a + this.b;
}
}
}
class minus extends operation {
constructor(a, b) {
super(1, '−', a, b);
}
calc() {
if (isNaN(this.a) || isNaN(this.b)){
return NaN;
} else {
return this.a - this.b;
}
}
}
class minus_r extends minus {
constructor(a, b) {
super(b, a);
}
}
class multiply extends operation {
constructor(a, b) {
super(2, '×', a, b);
}
calc() {
if (isNaN(this.a) || isNaN(this.b)){
return NaN;
} else {
return this.a * this.b;
}
}
}
class divide extends operation {
constructor(a, b) {
super(2, '÷', a, b);
}
calc() {
if (isNaN(this.a) || isNaN(this.b) || this.b === 0){
return NaN;
} else {
return this.a / this.b;
}
}
}
class divide_r extends divide {
constructor(a, b) {
super(b, a);
}
}
class Permutation {
constructor(arr) {
this.arr = Array.from(arr);
this.result = [];
this.len = 0;
this.run(0);
}
run(index) {
if (index == this.arr.length - 1) {
this.result.push(Array.from(this.arr));
this.len++;
return;
}
for(let i = index; i < this.arr.length; i++) {
[this.arr[index], this.arr[i]] = [this.arr[i], this.arr[index]];
this.run(index + 1);
[this.arr[index], this.arr[i]] = [this.arr[i], this.arr[index]];
}
}
}
class Product {
constructor(arr, len) {
this.arr = arr;
this.len = len;
this.result = [];
this.run();
}
run() {
for (let i = 0; i < Math.pow(this.arr.length, this.len); i++) {
this.result.push(this.convert(i, this.arr.length, this.len));
}
}
convert(n, base, digits) {
var result = [];
for (let i = 0; i < digits; i++) {
let m = n % base
n = (n - m) / base;
result.push(this.arr[m]);
}
return result;
}
}
new Vue({
el: "#app",
data: {
selected: [
{ data: "?" },
{ data: "?" },
{ data: "?" },
{ data: "?" }
],
error: false,
answers: [],
showanswers: false,
target: 24,
},
methods: {
clickBtn(event) {
for (i = 0; i < this.selected.length; i++) {
if (this.selected[i].data === '?') {
this.selected[i].data = event.target.innerText;
break;
}
}
this.error = false
},
reset() {
this.selected = [
{ data: "?" },
{ data: "?" },
{ data: "?" },
{ data: "?" }
];
this.error = false;
this.showanswers = false;
this.answers = [];
this.showanswers = false;
},
remove(index) {
this.selected[index].data = '?';
this.showanswers = false;
},
calc() {
var numbers = [];
for (i = 0; i < this.selected.length; i++) {
if (this.selected[i].data === '?') {
this.error = true;
} else {
numbers.push(parseInt(this.selected[i].data));
}
}
if (numbers.length < 4) {
return;
}
this.answers = [];
this.showanswers = true;
var operations = [add, minus, minus_r, multiply, divide, divide_r];
var numbers_permutation = new Permutation(numbers);
var operations_product = new Product(operations, numbers.length - 1);
for (let i = 0; i < numbers_permutation.result.length; i++) {
for (let j = 0; j < operations_product.result.length; j++) {
var r = numbers_permutation.result[i][0];
for (let k = 0; k < numbers.length - 1; k++) {
r = new operations_product.result[j][k](r, numbers_permutation.result[i][k + 1]);
}
if (Math.abs(r.calc() - this.target) < 0.0001) {
var find = false;
for (let l = 0; l < this.answers.length; l++) {
if (r.toString() === this.answers[l]) {
find = true;
break;
}
}
if (find === false) {
this.answers.push(r.toString());
}
}
}
}
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="24-point game">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
crossorigin="anonymous">
<script src="https://unpkg.com/vue"></script>
<title>24-Point Game</title>
<style>
.selected {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}
</style>
</head>
<body>
<div id="app" class="container">
<div class="jumbotron mt-2">
<h2><span class="badge badge-warning mr-2"><big>24</big></span>点游戏</h2>
<hr>
<p class="lead">选择<big class="font-weight-bold mr-2 ml-2">4</big>个数字(可以重复),通过四则运算得到<big class="badge badge-pill badge-success mr-2 ml-2">24</big>,即为胜利。</p>
</div>
<div class="row">
<div class="col">
<h4>请选数字:</h4>
</div>
</div>
<div class="row">
<div v-for="bt in 10" class="col-1">
<button type="button" class="btn btn-success" @click="clickBtn">{{ bt - 1 }}</button>
</div>
</div>
<hr>
<div class="row">
<div class="col">
<h4>已选数字:</h4>
</div>
</div>
<div v-if="error" class="alert alert-secondary">必须选择<span class="badge badge-warning mr-2 ml-2" style="font-size: 1.2rem">4</span>个数字才能计算!</div>
<div class="row">
<div v-for="(s, index) in selected" class="col-2">
<span class="selected badge" :class="[s.data === '?' ? 'badge-secondary' : 'badge-danger']" @click="remove(index)">{{s.data}}</span>
</div>
</div>
<hr>
<div class="row">
<div class="col">
<h4>开始:</h4>
</div>
</div>
<div class="row justify-content-center">
<div class="col">
<button type="button" class="btn btn-lg btn-success" @click="calc">计算</button>
<button type="button" class="btn btn-lg btn-secondary" @click="reset">重选</button>
</div>
</div>
<hr>
<div class="row">
<div class="col">
<table v-if="answers.length > 0" class="table table-striped">
<thead class="thead-light">
<tr>
<th>#</th>
<th>答案</th>
</tr>
</thead>
<tbody>
<tr v-for="(a, index) in answers">
<td>{{ index + 1 }}</td>
<td v-html="a"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-if="showanswers === true && answers.length ===0" class="alert alert-secondary">您选的数字无法计算出24。</div>
</div>
</body>
</html>
.selected {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}