这是一个高级/设计类型的问题,而不是任何具体的问题。
在这个游戏http://koreanwordgame.com/中,用户必须在一分钟内获得尽可能多的正确答案(尽管为了开发目的将其设置为5秒)。一分钟结束,我就用JQuery通过用户分数发起Ajax调用。
在服务器端,我使用此SQL查询获得5分以上和5分
$getquery = "(SELECT *
FROM highscore
WHERE score >= '$score'
ORDER BY score ASC
LIMIT 5)
UNION ALL
(SELECT *
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 5)";
这会向客户端返回一个HTML表格,您将在完成(5秒)挑战时看到该表格(您无需获得任何正确答案)。
现在,我最终希望表格大约有100行(尽管它仍然只会显示周围的10个单元格,上面5个,下面5个),行位置(ID)不是按时间顺序确定的,因为它现在是通过分数,如果有人得到1000个答案,他们将直接进入数据库的第1位。显然,如果用户低于表中已存在的100行中的任何一行,则应该简单地将其丢弃。然后当表返回时,我希望文本输入显示在放置用户的表格单元格中,这样他们就可以输入他们的名字并触发另一个Ajax调用,这样他们的条目就会插入到数据库中的正确位置。
我知道要求用户首先输入他们的详细信息然后舀掉前十名的结果会更容易,无论他们是否到达那里,但我的想法是我希望任何人能够得到某种因为这将鼓励人们发挥更多。
也许是一个艰难的人......我当然无法通过谷歌搜索找到类似的东西,所有人都非常感谢!
编辑:
如果有人对此感兴趣,这就是我最终的结果,它还远没有完成我需要更加强大,例如输入匿名用户名,以防用户关闭浏览器并防止双重帖子(尽管这会是客户方)。
但是谢谢大家的帮助,没有你我不会这样做。如果你看到任何明显的改进,可以随意指出它们!
<?php
$dbcon = mysql_connect("localhost", "XXXX", "XXXX") or die(mysql_error());
mysql_select_db("tulesblo_koreangame", $dbcon) or die(mysql_error());
mysql_query("SET NAMES utf8");
$name = $_POST["name"];
$email = $_POST["email"];
$score = $_POST["score"];
$table = "";
$submit = "";
$input = "";
$newposition = $_POST['position'];
$position = mysql_query("(SELECT position
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 1)");
if(!$name){
$gethigherrows = "(SELECT *
FROM highscore
WHERE score >= '$score'
ORDER BY score ASC
LIMIT 5)";
$getlowerrows = "(SELECT *
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 5)";
$higherrows= mysql_query($gethigherrows);
$lowerrows= mysql_query($getlowerrows);
if(mysql_error())echo mysql_error();
while($row=mysql_fetch_array($higherrows))
{
$uppertable .= "<tr><td>$row[position]</td><td>$row[name]</td> <td>$row[score]</td></tr>";
}
$x = 0;
if (mysql_num_rows($lowerrows) > 0)
{ mysql_query("UPDATE highscore SET position = position + 1 WHERE score < '$score'")or die("update failed");
while($row=mysql_fetch_array($lowerrows))
{
if ($x == 0)
{$position = $row['position'];};
$x++;
$newpos = $row[position]+1;
$lowertable.= "<tr><td>$newpos</td><td>$row[name]</td> <td>$row[score]</td></tr>";
}
$input = "<tr><td id='position'>$position</td><td><input id='nameinput'type='text' /></td><td>$score</td></tr>";
$submit = "<br />Enter email if you want to receive a prize!<br /><input id='emailinput'type='text' /><br /><input id='submithighscore'type='submit' value='Submit'>";
}
$table .= "<table id='scoretable'><tr><th>Position</th><th>Name</th><th>Score</th></tr>";
$table .= $uppertable;
$table .= $input;
$table .= $lowertable;
$table .= "</table>";
$table .= $submit;
$table .= "<br /><span class='msg'></span>";
echo $table;
}else{ echo($newposition);
mysql_query("INSERT INTO highscore VALUES (NULL, '$score', '$name', '$email', '$newposition')");
}
?>
答案 0 :(得分:3)
你没有说你的问题在哪里,但我想这主要是对SQL的误解。以下是我将如何处理整个应用程序。
对于SQL架构:
对于工作流程:
json_encode()
返回一个数组/对象)。否则,询问用户其名称,并发送新的AJAX请求。 SQL可以保持简单:
INSERT INTO Highscore SET name = ?, score = ?, when = NOW()
每次插入后,删除最低分
DELADE FROM Highscore ORDER BY得分ASC,当DESC LIMIT 1
如果你想防止作弊,你需要在你的ajax调用中添加哈希。例如,发送(用户名,得分,散列= md5(用户名.score。“secretphrase”)并检查散列是否仍与用户名和分数匹配。
UPDATE Highscore SET rank = rank + 1 WHERE score < ?
。答案 1 :(得分:0)
我有点理解你究竟追求的是什么。这是一个将结果插入高分的查询。
$str_user_id = $_GET['user_id'];
$str_score = $_GET['score'];
mysql_query("
INSERT INTO highscore (position, user_id, score)
SELECT (@rownum := $rownum + 1) AS position, user_id, score
FROM (SELECT user_id, score
FROM (SELECT '{$str_user_id}' AS user_id, '{$str_score}' AS score
UNION ALL
SELECT user_id, score
FROM highscore) AS h, (@rownum := 0) AS vars
WHERE '{$str_score}' <= 100
ORDER BY score ASC) AS h2)
LIMIT 100
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), score = VALUES(score)
");
答案 2 :(得分:0)
我无法完全理解你的问题,但基于此:
“我知道要求用户首先输入他们的详细信息然后舀掉前十名的结果会更容易,无论他们是否到达那里,但我的想法是我希望任何人能够得到某种入境,因为这将鼓励人们发挥更多“
我怀疑您希望向用户显示的分数表看起来像这样:
1. John Doe (score: 1,000,000)
2. Larry Roe (score: 999,999)
3. Jane Doe (score: 985,742)
...
5746. Susan Player (score: 894)
5747. *** YOU *** (score: 893)
5748. Joe R. Player (score: 889)
我的第二个Mytskine的初步建议是你不应该尝试将排名保存在数据库中 - 保持排名列更新是可能的,就像Mytskine在答案结束时显示的那样,但这是很多工作几乎没有任何收获。只需让您的分数表包含明显的列,例如name
和score
以及time
,再加上AUTO_INCREMENT列id
。
现在,假设你想要在新得分前后显示N个得分最高的球员,以及K球员。首先,我们需要弄清楚玩家的等级:
SELECT COUNT(*) + 1 FROM scores WHERE score > ?
此处,?
是玩家得分的占位符。这将计算有多少玩家得分高于我们下面要插入的分数。如果我们赞成关系中的最新分数,那么加一个将是玩家的等级。让我们用R来表示这个等级。
现在,如果R&lt; N + K,我们可能只是显示最高N + 2 * K(或最大(N,R + K)或其他)条目:
SELECT * FROM scores ORDER BY score DESC, time DESC LIMIT N+2*K
否则,我们需要分三步完成:首先,获取前N个条目:
SELECT * FROM scores ORDER BY score DESC, time DESC LIMIT N
然后,玩家上方的K条目:
SELECT * FROM scores WHERE score > ? ORDER BY score ASC, time ASC LIMIT K
最后是玩家下方的K个条目:
SELECT * FROM scores WHERE score <= ? ORDER BY score DESC, time DESC LIMIT K
请注意,第二个结果集将按相反顺序排列,但这没关系 - 只需在PHP中将其反转即可。现在我们需要为我们提取的条目分配排名,但这很简单:第一组的排名为1到N,第二组(反转后)排名RK为R-1,最后一组排名为R + 1至R + K. (等级R当然属于当前的玩家。)
最后,在玩家输入他们的名字之后,我们可以简单地将玩家的分数插入数据库:
INSERT INTO scores (name, score, time) VALUES (?, ?, ?)
如果你愿意,你也可以从这个时候删除数据库中的最低分数来限制它的大小,但实际上除非你有数十亿玩家,否则它可能无关紧要。 (单个分数条目将占用几十个字节,主要取决于播放器输入的名称的长度,因此一百万个条目仍然只有几十兆字节。)但是,您应该记住创建一个索引。 (score, time)
以保持查询效率。